【问题标题】:Get type of expression at compile time在编译时获取表达式类型
【发布时间】:2016-09-22 19:13:42
【问题描述】:

在使用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&amp;。最好尝试编译代码并获取elem 的类型以尽早发现此类错误。

【问题讨论】:

  • 不确定你在问什么。您为确保elem 是一个引用而编写的任何代码似乎都比一开始​​就编写auto&amp;&amp; elem 要长得多。
  • 您可以将std::is_referencestatic_assert 一起使用。但是将它添加到每个循环中不仅仅是确保您使用正确的类型开始。不,没有办法让编译器为你做检查,因为赋值在任何方面都不是无效的。
  • 您的示例看起来像是一个编译器警告的好理由。例如,我的编译器说warning: variable ‘elem’ set but not used
  • IIRC, auto 绝不是引用类型。您是否希望编译器从赋值的存在中推断出您打算使用引用并警告您?

标签: c++ c++11 c++14


【解决方案1】:

经典的方式是不用定义就声明模板结构:

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

Demo

顺便说一句,现在一些 IDE 会在鼠标悬停在 auto 或变量上时显示类型。

【讨论】:

  • 太棒了!我更喜欢这个——不幸的是,我的 Google-foo 找不到这种类型的解决方案:(
【解决方案2】:

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

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&amp; elem : s)给了

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

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

所以看来我可以在编译时找出类型并中止。这对于一个由几个 typedef 和模板参数组成的非常复杂的类型非常有用,我只是看不到发生了什么。

【讨论】:

    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 2016-11-22
    • 1970-01-01
    相关资源
    最近更新 更多