Asked  7 Months ago    Answers:  5   Viewed   96 times

I was somehow surprised that the following code compiles and runs (vc2012 & gcc4.7.2)

class Foo {
    struct Bar { int i; };
public:
    Bar Baz() { return Bar(); }
};

int main() {
    Foo f;
    // Foo::Bar b = f.Baz();  // error
    auto b = f.Baz();         // ok
    std::cout << b.i;
}

Is it correct that this code compiles fine? And why is it correct? Why can I use auto on a private type, while I can't use its name (as expected)?

 Answers

13

The rules for auto are, for the most part, the same as for template type deduction. The example posted works for the same reason you can pass objects of private types to template functions:

template <typename T>
void fun(T t) {}

int main() {
    Foo f;
    fun(f.Baz());         // ok
}

And why can we pass objects of private types to template functions, you ask? Because only the name of the type is inaccessible. The type itself is still usable, which is why you can return it to client code at all.

Tuesday, June 1, 2021
 
Kwadz
answered 7 Months ago
51

Edit: Using the new concept of Size Classes introduced in Xcode 6, you can easily setup different constraints for specific size classes in Interface Builder. Most devices (e.g. all current iPhones) have a Compact vertical size class in landscape mode.

This is a much better concept for general layout decisions than determining the device's orientation.

That being said, if you really need to know the orientation, UIDevice.currentDevice().orientation is the way to go.


Original post:

Override the updateViewConstraints method of UIViewController to provide layout constraints for specific situations. This way, the layout is always set up the correct way according to situation. Make sure they form a complete set of constraints with those created within the storyboard. You can use IB to set up your general constraints and mark those subject to change to be removed at runtime.

I use the following implementation to present a different set of constraints for each orientation:

-(void)updateViewConstraints {
    [super updateViewConstraints];

    // constraints for portrait orientation
    // use a property to change a constraint's constant and/or create constraints programmatically, e.g.:
    if (!self.layoutConstraintsPortrait) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    // constraints for landscape orientation
    // make sure they don't conflict with and complement the existing constraints
    if (!self.layoutConstraintsLandscape) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
    [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait];
    [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape];        
}

Now, all you need to do is trigger a constraint update whenever the situation changes. Override willAnimateRotationToInterfaceOrientation:duration: to animate the constraint update on orientation change:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];

}
Tuesday, June 22, 2021
 
Daveel
answered 6 Months ago
92

The type of childs will be std::vector<something>.

auto is powered by the same rules as template type deduction. The type picked here is the same that would get picked for template <typename T> f(T t); in a call like f(node->getChilds()).

Similarly, auto& would get you the same type that would get picked by template <typename T> f(T& t);, and auto&& would get you the same type that would get picked by template <typename T> f(T&& t);.

The same applies for all other combinations, like auto const& or auto*.

Thursday, August 5, 2021
 
Naveed S
answered 4 Months ago
35
auto& get_diag2(int(&ar)[3][3]){ // adding & auto because otherwise it converts the array to pointer
    static int diag[3]{
        ar[0][0], ar[1][1], ar[2][2]
    };
    return diag;
}

Will not work in a C++11 compiler. Using auto without a trailing return type was added to C++14 and acts like how auto works when using it for a variable. This means it will never return a reference type so you have to use auto& to return a reference to the thing you want to return.

If you do not know if you should return a reference or a value (this happens a lot in generic programming) then you can use decltyp(auto) as the return type. For example

template<class F, class... Args>
decltype(auto) Example(F func, Args&&... args) 
{ 
    return func(std::forward<Args>(args)...); 
}

will return by value if func returns by value and return by reference if func returns a reference.


In short if you are using C++11 you have to specify the return type, either in front or as a trailing return type. In C++14 and above you can just use auto/decltype(auto) and let the compiler deal with it for you.

Friday, September 17, 2021
 
Daniel H
answered 3 Months ago
58

Once the type of the initializer has been determined, the compiler determines the type that will replace the keyword auto using the rules for template argument deduction from a function call (see template argument deduction#Other contexts for details). The keyword auto may be accompanied by modifiers, such as const or &, which will participate in the type deduction.

For example, given

const auto& i = expr;

The type of i is exactly the type of the argument u in an imaginary

template template<class U> 
void f(const U& u)

If the function call f(expr) was compiled.

In general , it can be think as below .

 template template<class U> 
    void f(paramtype u)

Therefore, auto&& may be deduced either as an lvalue reference or rvalue reference according to the initializer.

In your case , imaginary template would look like

 template template<class U> 
        void f(U&& var2){}
f(var1) 

Here ,var1 is named rvalue which is being treated as lvalue, so var2 will be deduced as lvalue .

Consider the following examples:

auto&& var2 = widget() ; //var2 is rvalue reference here .
int x=10;
const int cx=10;
auto&& uref1 = x; // x is int and lvalue, so uref1's type is int&
auto&& uref2 = cx; // cx is const int and lvalue,  so uref2's type is const int&
auto&& uref3 = 27; // 27 is int and rvalue,  so uref3's type is int&&
Saturday, November 20, 2021
 
SkyNet
answered 2 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share