是否可以在C ++编译期间使用模板元编程输出评估值?

时间:2013-08-03 09:44:26

标签: c++ compilation

箱, 我在科学研究期间遇到了一个问题,是否有可能在编译期间输出评估值?可以确定编译器在编译期间计算表达式,关键是我们如何在编译期间输出评估值?一种方法是强制错误,但似乎不是很优雅。如果我想使用TMP,是否可以这样做?感谢。

3 个答案:

答案 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;
                                     ^

如果您对这些值感兴趣但仍希望获得编译代码,那么我所知道的最佳方法是基于例如未使用的变量创建警告消息。由于标准从不需要警告,因此它会依赖于编译器和显示警告时使用的标志。使用gccclang进行测试表明,如果简单地定义了上述类模板,则编译器不会显示模板参数的值。以下代码显示[当前]编译器在诊断中报告的内容不同:

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存储器的方式。