2

小伙伴们,我在做科研的时候遇到一个问题,是否可以在编译时输出评估值?编译器肯定会在编译时评估表达式,关键是我们如何在编译期间输出评估值?一种方法是强制错误,但似乎不是很优雅。如果我想使用 TMP,可以吗?谢谢。

4

3 回答 3

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过,但没有提到问题发生的模板实例化。您将需要与您正在使用的编译器一起使用的那种形式的东西(可能需要根据您正在使用的编译器版本进行定制)。

于 2013-08-03T10:08:50.450 回答
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

于 2013-08-03T10:11:41.837 回答
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 存储器。

于 2014-06-28T11:44:22.880 回答