Duck Typing (Err, auto) Without A Duck

Motivation

Much ado about nothing …
vector<MyType>::iterator
  iter = v.begin();
Compiler knows anyway ⟶ iterator
auto iter = v.begin();
Compiler knows anyway ⟶ const_iterator
auto iter = v.cbegin();
Lambdas have no spellable type, intentionally
auto func = [](){};
  • Type Deduction

  • Compiler knows anyway

  • He always knew ⟶ lookup of template specializations

  • ⟶ Same rules apply

Most Basic Usage

  • No reference (&)

  • ⟶ all fine, nobody is confused

#include <iostream>
using namespace std;

int main()
{
    int i = 42;
    auto j = i; // int j

    cout << "i: " << i << ", &i: " << &i << endl;
    cout << "j: " << j << ", &j: " << &j << endl;

    return 0;
}
$ ./c++11-auto-most-basic
i: 42, &i: 0x7ffcd604846c
j: 42, &j: 0x7ffcd6048468

auto Is Only The Basic Type

  • Ignores References

  • Ignores const

#include <iostream>
using namespace std;

int main()
{
    int i = 42;
    int& iref = i;
    auto j = iref;   // <--- int j (not reference)

    j = 666;  // does *not* assign through to i

    cout << "i: " << i << ", &i: " << &i << endl;
    cout << "iref: " << iref << ", &iref: " << &iref << endl;
    cout << "j: " << j << ", &j: " << &j << endl;

    return 0;
}
$ ./c++11-auto-ref-pitfall
i: 42, &i: 0x7ffffefe2b54
iref: 42, &iref: 0x7ffffefe2b54
j: 666, &j: 0x7ffffefe2b50

If You Want Reference, Say So!

#include <iostream>
using namespace std;

int main()
{
    int i = 42;
    int& iref = i;
    auto& j = iref;

    j = 666;  // *does* assign through to i

    cout << "i: " << i << ", &i: " << &i << endl;
    cout << "iref: " << iref << ", &iref: " << &iref << endl;
    cout << "j: " << j << ", &j: " << &j << endl;

    return 0;
}
$ ./c++11-auto-ref
i: 666, &i: 0x7ffc59ebd7bc
iref: 666, &iref: 0x7ffc59ebd7bc
j: 666, &j: 0x7ffc59ebd7bc

If You Want Const-Reference, Say So!

#include <iostream>
using namespace std;

int main()
{
    int i = 42;
    const auto& ciref = i;

    cout << "i: " << i << ", &i: " << &i << endl;
    cout << "ciref: " << ciref << ", &ciref: " << &ciref << endl;

    return 0;
}
$ ./c++11-auto-const-ref
i: 42, &i: 0x7ffc23e46284
ciref: 42, &ciref: 0x7ffc23e46284

If You Want Pointer, Say So!

#include <iostream>
using namespace std;

int main()
{
    int i = 42;
    auto* pi = &i;

    *pi = 666;

    cout << "i: " << i << ", &i: " << &i << endl;
    cout << "pi: " << pi << endl;

    return 0;
}
$ ./c++11-auto-pointer
i: 666, &i: 0x7ffe4a148064
pi: 0x7ffe4a148064

And Arrays? Decay To Pointers!

#include <iostream>
using namespace std;

int main()
{
    int array[] = { 1, 2, 3 };
    auto p = array;

    cout << "array: " << array << ", &array: " << &array << endl;
    cout << "p: " << p << endl;

    return 0;
}
$ ./c++11-auto-array
array: 0x7ffc528e013c, &array: 0x7ffc528e013c
p: 0x7ffc528e013c