在编译时获取表达式的类型

Get type of expression at compile time

本文关键字:类型 表达式 获取 编译      更新时间:2023-10-16

在使用auto关键字进行编程时,有时知道编译器在编译时使用的类型是很方便的。如果编译在我需要知道类型的地方中止,这并不重要。简单的例子:

std::vector< int > s{1, 2, 3}; 
for (auto elem : s) {
    elem = 5;
}   
for (auto elem : s) {
    std::cout << elem << std::endl;
}   

将打印

1
2
3

是因为elem的类型是int,而不是int&。最好尝试编译代码并获得elem的类型,以便尽早捕获此类错误。

经典的方法是声明模板结构而不定义:

template <typename> struct Debug;

,然后使用:

template struct Debug<std::string>;

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

消息错误看起来像

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)>{};

演示

顺便说一句,现在一些ide显示类型时,鼠标在auto或变量。

其实我刚刚找到了自己问题的答案:

template<typename T>
void show_type_abort_helper()
{
    return __PRETTY_FUNCTION__;
}
#define show_type_abort(x) show_type_abort_helper< decltype(x) >()

用法:

std::vector< int > s{1, 2, 3};
for (auto elem : s) {
    show_type_abort(elem);
    elem = 5;
}

使用g++(版本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__;

检查T = int的输出,查看编译器使用int作为类型。这似乎也适用于clang:

$ 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);

更改为for (const auto& elem : s)给出

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

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

所以看起来我可以在编译时找到类型并中止。对于由几个typedef和模板参数组成的非常复杂的类型,我无法看到发生了什么,这就派上了用场。

相关文章: