箱, 我在科学研究期间遇到了一个问题,是否有可能在编译期间输出评估值?可以确定编译器在编译期间计算表达式,关键是我们如何在编译期间输出评估值?一种方法是强制错误,但似乎不是很优雅。如果我想使用TMP,是否可以这样做?感谢。
答案 0 :(得分:2)
假设您想要查看整型常量表达式的值,查看调试目的值的简便方法是使用该值创建错误。例如:
template <int> struct constexpr_debugger;
int main() {
const int i0(4), i1(17);
constexpr_debugger<i0 + i1> debug;
}
编译此代码时,我收到消息
constexpr_debugger.cpp: In function ‘int main()’:
constexpr_debugger.cpp:5:37:error: aggregate ‘constexpr_debugger<21> debug’ has incomplete type and cannot be defined
constexpr_debugger<i0 + i1> debug;
^
如果您对这些值感兴趣但仍希望获得编译代码,那么我所知道的最佳方法是基于例如未使用的变量创建警告消息。由于标准从不需要警告,因此它会依赖于编译器和显示警告时使用的标志。使用gcc和clang进行测试表明,如果简单地定义了上述类模板,则编译器不会显示模板参数的值。以下代码显示[当前]编译器在诊断中报告的内容不同:
template <int>
void constexpr_debugger()
{
int debug;
}
int main() {
const int i0(4), i1(17);
constexpr_debugger<i0 + i1>();
}
gcc提到函数包括其模板参数,因此,当警告debug
未被使用时,会提到所需的值。 clang也警告debug
,但没有提到问题发生的模板实例化。你需要一些适合你正在使用的编译器的形式(可能需要根据你正在使用的编译器版本进行定制)。
答案 1 :(得分:1)
从C ++ 11开始,可以使用constexpr
来启用在编译时计算表达式
示例:
constexpr int sqr(int x)
{
return x*x;
}
int a[sqr(4)]; //Compiles with C++11 and a has 16 elements.
用于显示评估表达式使用模板元编程
template<unsigned int n>
struct dummy ;
int main() {
char<dummy1<dummy<1 + 55-2>::dummy2>()); //Obliviously wrong
return 0;
}
编译器出错:
error: incomplete type 'dummy<54u>' used in nested name specifier
答案 2 :(得分:0)
如果您不喜欢使用编译错误或警告,可以将类型信息放入目标文件中的符号中。以下程序将为编译时列表执行此操作。
// Just define the types we need to construct lists.
template <typename Head, typename Tail> struct Cons {};
struct Nil {};
// This is what you want to output.
using MyOutput = Cons<int, Cons<float, Cons<char, Nil>>>;
// Template function declaration.
template <typename TheOutput>
void MyOutputFunc () {}
// Explicitly instantiate the template function with the desired output.
template void MyOutputFunc<MyOutput> ();
检索输出将是编译器,也许是特定于操作系统的。以下为Linux上的g ++演示了这一点。
$ g++ -c -std=c++11 a.cpp
$ nm a.o | grep MyOutputFunc
0000000000000000 W _Z12MyOutputFuncI4ConsIiS0_IfS0_Ic3NilEEEEvv
$ nm a.o | grep MyOutputFunc | cut -d ' ' -f3 | c++filt
void MyOutputFunc<Cons<int, Cons<float, Cons<char, Nil> > > >()
您可以通过将它们包装在以下类型中来输出整数:
template <typename T, T value>
struct WrapValue {};
using MyOutput = WrapValue<int, 15>;
这对于检索各种支持信息而不是调试更有用。例如,我的这种方法的用例与某些微控制器软件的配置选项有关,编译时输出是模板程序将配置选项映射到EEPROM存储器的方式。