tags:

views:

138

answers:

2

Hello,

auto a = (Foo<T>*)malloc(sizeof(Foo<T>));
auto *b = (Foo<T>*)malloc(sizeof(Foo<T>));

I don't think it's important that templates are there, but the question is: are a and b of the same type?

g++ -std=c++0x -Wall (4.4) doesn't give any errors or warnings, but I haven't run the program so I don't know if it does the same thing.

Does this mean that for a, auto is Foo<T>*, but for b, auto is Foo<T>?

+11  A: 

are a and b of the same type?

Let's find out, shall we?

#include <cstdlib>
#include <type_traits>

template <typename T>
struct Foo
{
    T member;
};

template <typename T>
void test()
{
    auto  a = (Foo<T>*)malloc(sizeof(Foo<T>));
    auto *b = (Foo<T>*)malloc(sizeof(Foo<T>));

    static_assert(std::is_same<decltype(a), decltype(b)>::value, "same type");
}

template void test<int>();   // explicit instantiation

This compiles without a static assertion failure.

Does this mean that for a, auto is Foo<T>*, but for b, auto is Foo<T>?

Yes.

FredOverflow
`decltype` is redundant.
ybungalobill
Worse, it hides the theoretical possibility that `typeid(a) != typeid (b)`.
MSalters
@ybu @MSa update
FredOverflow
@MSalters: Maybe I'm not following, but those must compare equal if they are the same type (though they don't have to be the same object). @Fred: Maybe a better answer would just be an `is_same` meta-function and printing `is_same<decltype(a), decltype(b)>::value`.
GMan
@GMan: How do you like my update? :)
FredOverflow
@Fred: Much simpler. :)
GMan
Nice trick, thanks!
raicuandi
@GMan: your statement is correct, but weak. You can't invert it. I.e. "they _may or may not_ compare inequal if they are not the same type". Because of this weakness, your (previous) `static_assert` does not conclusively establish that `a` and `b` are the same type.
MSalters
+2  A: 

You can think of auto as a placeholder. In your example the declared types of a and b are same. The only difference is that auto is deduced to be the pointer itself in the first case whereas in the second case it is deduced to be just Foo<T>.

Except for one special case, auto works just like template argument deduction with a function:

template<class U>
void func_a(U);

template<class U>
void func_b(U*);

template<class T> struct Foo {};

template<class T>
void test() {
   func_a( new Foo<T> ); // U = Foo<T>*
   func_b( new Foo<T> ); // U = Foo<T>
}

In your example auto is deduced just like the type parameter U in the above code.

The special case I was talking about are initializer lists:

void test2() {
    auto x = {1,2,3};  // OK, decltype(x) --> initializer_list<int>
    func_a( {1,2,3} ); // Illegal, U cannot be deduced because
                       // {1,2,3} is not considered an expression
}

Apart from this special case, the deduction rules are the same.

sellibitze