I've wrote several constexpr functions and use them in static_asserts to control some resource limits. But I'd like to not only enforce compile-time predicate but also to see the actual values calculated during normal compilation process or at least when assertion fails.
我已经编写了几个constexpr函数,并在static_assert中使用它们来控制一些资源限制。但是,我不仅希望强制执行编译时谓词,还希望看到在正常编译过程中或至少在断言失败时计算的实际值。
There are ways to print string messages during compilation, but what's about printing results of constexpr computations?
在编译期间可以打印字符串消息,但是如何打印constexpr计算的结果呢?
2 个解决方案
#1
5
Here is some code that exploits gcc's diagnostic messages to print values of interest after an assert message. To find the values of interest, you just need to search the error string for T x =
:
下面是一些代码,它们利用gcc的诊断消息在断言消息之后打印感兴趣的值。要找到感兴趣的值,只需搜索T x的错误字符串=:
#include <string>
template <class T, T x, class F>
void transparent(F f) { f(); }
template <bool B>
constexpr void my_assert() {
static_assert(B, "oh no");
}
template <int X>
void f() {
transparent<int, X+7>([]{
transparent<long, X*X*X>([]{
my_assert<X+10==-89>(); });});
}
int main() {
// f<3>();
f<4>();
// f<-99>();
}
Here is the error that it got me:
这是它带给我的错误:
g++ h.cpp -std=c++11 h.cpp: In instantiation of ‘constexpr void my_assert() [with bool B = false]’: h.cpp:16:34: required from ‘f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:15:35: required from ‘struct f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:16:38: required from ‘f() [with int X = 4]::__lambda0’ h.cpp:14:28: required from ‘struct f() [with int X = 4]::__lambda0’ h.cpp:16:41: required from ‘void f() [with int X = 4]’ h.cpp:21:10: required from here h.cpp:9:5: error: static assertion failed: oh no static_assert(B, "oh no"); ^ h.cpp:4:6: error: ‘void transparent(F) [with T = long int; T x = 64l; F = f() [with int X = 4]::__lambda0::__lambda1]’, declared using local type ‘f() [with int X = 4]::__lambda0::__lambda1’, is used but never defined [-fpermissive] void transparent(F f) { f(); } ^ h.cpp:4:6: error: ‘void transparent(F) [with T = int; T x = 11; F = f() [with int X = 4]::__lambda0]’, declared using local type ‘f() [with int X = 4]::__lambda0’, is used but never defined [-fpermissive]
g++ h。cpp化c++ 11 h。cpp:在实例化‘constexpr void my_assert() [with bool B = false] ': h。cpp:16:34:要求从f()[与int X = 4]::__lambda0::__lambda1 ' h。cpp:15:35:“struct f()”要求[与int X = 4]::__lambda0::__lambda1 ' h。cpp:16:38: f()要求[int X = 4]::__lambda0 ' h。cpp:14:28: struct f() [with int X = 4]: __lambda0 ' h。cpp:16:41:要求从' void f() [with int X = 4] ' h。cpp:21:10:这里要求h。错误:静态断言失败:oh no static_assert(B,“oh no”);^ h。错误:“void transparent(F)”[with T = long int]T x = 64升;F = F () [with int X = 4]: __lambda0::__lambda1] ',使用局部类型' F () [with int X = 4]:::__lambda0:::} ^ h。错误:“void transparent(F)”[with T = int]T x = 11;F = F () [with int X = 4]: __lambda0] ',使用局部类型' F () [with int X = 4]::__lambda0 '声明,但从未定义
Note that bolded parts
注意粗体部分
#2
0
My VC++ code that print, during compilation, the value of as many compile time constants as you like (e.g. sizeof structures) and continue compiling without error:
我的vc++代码,在编译过程中,输出您喜欢的编译时间常量的值(例如sizeof结构),并继续编译,没有错误:
// cpptest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//#define VALUE_TO_STRING2(x) #x
//#define VALUE_TO_STRING(x) VALUE_TO_STRING2(x)
#define TO_STRING(x) #x
#define FUNC_TEMPLATE_MSG(x,y) "[" x "]""["TO_STRING(y)"]"
template<unsigned int N,unsigned int M>
int printN()
{
#pragma message(FUNC_TEMPLATE_MSG(__FUNCSIG__ ,1))
return 0;
};
struct X {
char a[20];
int b;
};
struct Y {
char a[210];
int b;
};
int _tmain(int argc, _TCHAR* argv[])
{
printN<sizeof(X),__COUNTER__>();
printN<sizeof(Y),__COUNTER__>();
//..as many compile time constants as you like
}
Sample output produced by VC++2010. The target value is the first function template parameter value (0x18 and 0xd8 in the example) which VC++ oddly chose to output as hexadecimal value!!
vc++ 2010年生产的样品。目标值是第一个函数模板参数值(在示例中为0x18和0xd8), vc++奇怪地选择输出为十六进制值!!
1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1> cpptest.cpp
1> [int __cdecl printN<0x18,0x0>(void)][1]
1> [int __cdecl printN<0xd8,0x1>(void)][1]
1> Generating code
1> Finished generating code
1> cpptest.vcxproj -> c:\work\cpptest\Release\cpptest.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
The major technique used here is that a during each function template instantiation, the #pragma message()
directive is invoked once. The Microsoft specific macro __FUNCSIG__
can display the signature of the containing function and thus the integer value used in each specific instantiation of the function template. Giving COUNTER
as the second template parameter is to make sure 2 integers of the same value are still considered different. The 1 in the #pragma
directive is of no use here but can be used as an identifier in case we have more than 1 such directive and the output window is full of messy messages.
这里使用的主要技术是在每个函数模板实例化过程中调用一次#pragma message()指令。Microsoft特定的宏__FUNCSIG__可以显示包含函数的签名,从而显示函数模板每个特定实例化中使用的整数值。将计数器作为第二个模板参数是为了确保相同值的两个整数仍然被认为是不同的。#pragma指令中的1在这里没有用处,但是如果我们有超过1个这样的指令并且输出窗口充满了混乱的消息,则可以作为标识符使用。
#1
5
Here is some code that exploits gcc's diagnostic messages to print values of interest after an assert message. To find the values of interest, you just need to search the error string for T x =
:
下面是一些代码,它们利用gcc的诊断消息在断言消息之后打印感兴趣的值。要找到感兴趣的值,只需搜索T x的错误字符串=:
#include <string>
template <class T, T x, class F>
void transparent(F f) { f(); }
template <bool B>
constexpr void my_assert() {
static_assert(B, "oh no");
}
template <int X>
void f() {
transparent<int, X+7>([]{
transparent<long, X*X*X>([]{
my_assert<X+10==-89>(); });});
}
int main() {
// f<3>();
f<4>();
// f<-99>();
}
Here is the error that it got me:
这是它带给我的错误:
g++ h.cpp -std=c++11 h.cpp: In instantiation of ‘constexpr void my_assert() [with bool B = false]’: h.cpp:16:34: required from ‘f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:15:35: required from ‘struct f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:16:38: required from ‘f() [with int X = 4]::__lambda0’ h.cpp:14:28: required from ‘struct f() [with int X = 4]::__lambda0’ h.cpp:16:41: required from ‘void f() [with int X = 4]’ h.cpp:21:10: required from here h.cpp:9:5: error: static assertion failed: oh no static_assert(B, "oh no"); ^ h.cpp:4:6: error: ‘void transparent(F) [with T = long int; T x = 64l; F = f() [with int X = 4]::__lambda0::__lambda1]’, declared using local type ‘f() [with int X = 4]::__lambda0::__lambda1’, is used but never defined [-fpermissive] void transparent(F f) { f(); } ^ h.cpp:4:6: error: ‘void transparent(F) [with T = int; T x = 11; F = f() [with int X = 4]::__lambda0]’, declared using local type ‘f() [with int X = 4]::__lambda0’, is used but never defined [-fpermissive]
g++ h。cpp化c++ 11 h。cpp:在实例化‘constexpr void my_assert() [with bool B = false] ': h。cpp:16:34:要求从f()[与int X = 4]::__lambda0::__lambda1 ' h。cpp:15:35:“struct f()”要求[与int X = 4]::__lambda0::__lambda1 ' h。cpp:16:38: f()要求[int X = 4]::__lambda0 ' h。cpp:14:28: struct f() [with int X = 4]: __lambda0 ' h。cpp:16:41:要求从' void f() [with int X = 4] ' h。cpp:21:10:这里要求h。错误:静态断言失败:oh no static_assert(B,“oh no”);^ h。错误:“void transparent(F)”[with T = long int]T x = 64升;F = F () [with int X = 4]: __lambda0::__lambda1] ',使用局部类型' F () [with int X = 4]:::__lambda0:::} ^ h。错误:“void transparent(F)”[with T = int]T x = 11;F = F () [with int X = 4]: __lambda0] ',使用局部类型' F () [with int X = 4]::__lambda0 '声明,但从未定义
Note that bolded parts
注意粗体部分
#2
0
My VC++ code that print, during compilation, the value of as many compile time constants as you like (e.g. sizeof structures) and continue compiling without error:
我的vc++代码,在编译过程中,输出您喜欢的编译时间常量的值(例如sizeof结构),并继续编译,没有错误:
// cpptest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//#define VALUE_TO_STRING2(x) #x
//#define VALUE_TO_STRING(x) VALUE_TO_STRING2(x)
#define TO_STRING(x) #x
#define FUNC_TEMPLATE_MSG(x,y) "[" x "]""["TO_STRING(y)"]"
template<unsigned int N,unsigned int M>
int printN()
{
#pragma message(FUNC_TEMPLATE_MSG(__FUNCSIG__ ,1))
return 0;
};
struct X {
char a[20];
int b;
};
struct Y {
char a[210];
int b;
};
int _tmain(int argc, _TCHAR* argv[])
{
printN<sizeof(X),__COUNTER__>();
printN<sizeof(Y),__COUNTER__>();
//..as many compile time constants as you like
}
Sample output produced by VC++2010. The target value is the first function template parameter value (0x18 and 0xd8 in the example) which VC++ oddly chose to output as hexadecimal value!!
vc++ 2010年生产的样品。目标值是第一个函数模板参数值(在示例中为0x18和0xd8), vc++奇怪地选择输出为十六进制值!!
1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1> cpptest.cpp
1> [int __cdecl printN<0x18,0x0>(void)][1]
1> [int __cdecl printN<0xd8,0x1>(void)][1]
1> Generating code
1> Finished generating code
1> cpptest.vcxproj -> c:\work\cpptest\Release\cpptest.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
The major technique used here is that a during each function template instantiation, the #pragma message()
directive is invoked once. The Microsoft specific macro __FUNCSIG__
can display the signature of the containing function and thus the integer value used in each specific instantiation of the function template. Giving COUNTER
as the second template parameter is to make sure 2 integers of the same value are still considered different. The 1 in the #pragma
directive is of no use here but can be used as an identifier in case we have more than 1 such directive and the output window is full of messy messages.
这里使用的主要技术是在每个函数模板实例化过程中调用一次#pragma message()指令。Microsoft特定的宏__FUNCSIG__可以显示包含函数的签名,从而显示函数模板每个特定实例化中使用的整数值。将计数器作为第二个模板参数是为了确保相同值的两个整数仍然被认为是不同的。#pragma指令中的1在这里没有用处,但是如果我们有超过1个这样的指令并且输出窗口充满了混乱的消息,则可以作为标识符使用。