Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

difference between auto and decltype in c++0x

I'm having trouble with auto and decltype.

void f(const vector<int>& a, vector<float>& b)
{
    typedef decltype(a[0]*b[0]) Tmp;
    for (int i=0; i < b.size(); ++i) {
      auto p0 = new auto(a[i]*b[i]);
      auto p1 = new decltype(a[i]*b[i]);
      *p0=a[i]*b[i];
      *p1=a[i]*b[i];
      cout<<*p0<<endl;
      cout<<*p1<<endl;
      delete p0;
      delete p1;
   }
}

 int main()
{

    vector<float>vec2;
    vec2.push_back(2.0);

    vector<int>vec1;
    vec1.push_back(5);

    return 0;
}

The above code runs well in GCC4.7. Could I use 'new auto(a[0]*b[0])' to allocate memory for the type of a[0]*b[0]? And I can not distinguish the difference between decltype and auto in this case.

like image 782
Leonhart Squall Avatar asked Jun 07 '12 15:06

Leonhart Squall


1 Answers

The difference is that this:

  new auto(a[i]*b[i]);

is allocating an object of whatever type a[i]*b[i] is, and initializes the object with that value. That is, the parentheses are an initializer. Whereas using decltype:

  new decltype(a[i]*b[i]);

allocates an object of the same type, but there is no initializer. The object is default initialized.

Basically decltype(...) is treated as a type, while auto specifies a type to be deduced from an intializer.


C++11 Style

Since new shouldn't be used except in special cases, if for some reason these semantics are needed they'd properly be written something like this:

template<typename T, typename... Args> T make_unique(Args &&...args) {
  return std::unique_ptr<T>{std::forward<Args>(args)...};
}

template<typename T> T make_unique_auto(T &&t) {
    return std::unique_ptr<T>{std::forward<T>(t)};
}

// new auto(a[i]*b[i])
auto p1 = make_unique_auto(a[i]*b[i]);

// new decltype(a[i]*b[i])
auto p2 = make_unique<decltype(a[i]*b[i])>();

Furthermore, if one gets used to using C++11 uniform initialization universally the and if one stops using parentheses for initialization then eventually the parentheses used with decltype cease to look to the programmer like an initializer.

For this reason and others, I think it would be good for a 'modern' C++11 style to include a rule that one should always use braces and never use parentheses for initialization. (And constructors that cannot be called except with parentheses, e.g. std::vector<int>(int,int);, should be avoided; don't create new ones and don't use legacy ones.)

like image 101
bames53 Avatar answered Sep 23 '22 17:09

bames53