hochl
hochl

Reputation: 12940

Get type of expression at compile time

While programming with the auto keyword it would sometimes be convenient to know the type that is used by the compiler at compile time. It does not matter if the compilation aborts where I need to know the type. Simple example:

std::vector< int > s{1, 2, 3}; 

for (auto elem : s) {
    elem = 5;
}   

for (auto elem : s) {
    std::cout << elem << std::endl;
}   

will print

1
2
3

because elem is of type int, not int&. It would be nice to try compile the code and get the type of elem to catch such mistakes early.

Upvotes: 4

Views: 5457

Answers (2)

Jarod42
Jarod42

Reputation: 217448

Classical way is to declare template structure without definition:

template <typename> struct Debug;

and then use it:

template struct Debug<std::string>;

or

for (auto elem : s) {
    Debug<decltype(elem)>{};

    elem = 5;
}

Message error looks like

error: explicit instantiation of 'struct Debug<std::__cxx11::basic_string<char> >' before definition of template
 template struct Debug<std::string>;
                 ^~~~~~~~~~~~~~~~~~

error: invalid use of incomplete type 'struct Debug<int>'
         Debug<decltype(e)>{};

Demo

BTW, now some IDEs show the type when mouse is over auto or the variable.

Upvotes: 14

hochl
hochl

Reputation: 12940

Actually I just found an answer to my own question:

template<typename T>
void show_type_abort_helper()
{
    return __PRETTY_FUNCTION__;
}

#define show_type_abort(x) show_type_abort_helper< decltype(x) >()

Usage:

std::vector< int > s{1, 2, 3};

for (auto elem : s) {
    show_type_abort(elem);
    elem = 5;
}

Produces the following error message with g++ (version 6.1.1):

$ g++ test.cpp
test.cpp: In instantiation of ‘void show_type_abort_helper() [with T = int]’:
                                                                       ^^^
test.cpp:17:9:   required from here
test.cpp:7:12: error: return-statement with a value, in function returning 'void' [-fpermissive]
    return __PRETTY_FUNCTION__;

Check the output at T = int to see the compiler uses int as type. This seems to work with clang as well:

$ clang++-3.8 -std=c++11 test.cpp
test.cpp:7:5: error: void function 'show_type_abort_helper' should not return a value [-Wreturn-type]
    return __PRETTY_FUNCTION__;
    ^      ~~~~~~~~~~~~~~~~~~~
test.cpp:17:9: note: in instantiation of function template specialization 'show_type_abort_helper<int>' requested here
                                                                                                  ^^^
        show_type_abort(elem);

Changing to for (const auto& elem : s) gives

with T = const int&
         ^^^^^^^^^^

or

show_type_abort_helper<const int &>
                       ^^^^^^^^^^^

So it seems I can find out the type at compile time and abort. This just came in handy for a very complex type that consisted of several typedefs and template parameters where I just could not see what was going on.

Upvotes: 3

Related Questions