在C++ 11中,模板中static_assert的操作是否应该取决于该模板是否已经实例化?例如,使用以下代码
template <int I>
void sa() { static_assert(0,"Hello."); }
int main(int argc, char *argv[]) { return 0; }
Run Code Online (Sandbox Code Playgroud)
GCC 4.5.0将无法断言,并生成"Hello".信息.另一方面,Digital Mars Compiler版本8.42n没有给出任何消息.
在C++中创建模板函数时,有一种简单的方法可以将模板的类型名称表示为字符串吗?我有一个简单的测试用例来展示我正在尝试做的事情(注意显示的代码不能编译):
#include <stdio.h>
template <typename type>
type print(type *addr)
{
printf("type is: %s",type);
}
int main()
{
int a;
print(&a);
}
// Would like to print something like:
// type is: int
Run Code Online (Sandbox Code Playgroud)
我认为在实例化函数时,typename应该在编译时可用,但我不熟悉模板,我还没有看到将typename作为字符串的方法.
我想这样做的原因是一些printf类型的调试.我有多个线程正在运行,并通过gdb逐步更改程序行为.所以对于某些事情,我想转储有关正在执行哪些函数的信息.这不是太重要,所以如果解决方案过于复杂,我会跳过将此信息添加到我的日志记录功能中.但如果有一种简单的方法可以做到这一点,那将是有用的信息.
template <int answer> struct Hitchhiker {
static_assert(sizeof(answer) != sizeof(answer), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
Run Code Online (Sandbox Code Playgroud)
在尝试禁用常规模板实例化的同时,static_assert我发现clang即使模板未实例化,上面的代码也会生成断言错误,而gcc只有在Hitchhiker使用除了以外的参数进行实例化时才生成断言错误42.
摆弄我发现这个断言:
template <int answer> struct Hitchhiker {
static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
Run Code Online (Sandbox Code Playgroud)
两个编译器的行为相同:只有在实例化通用模板时,断言才会启动.
标准说什么,哪个编译器是对的?
g++ 4.9.2
clang++ 3.50
Run Code Online (Sandbox Code Playgroud) 我有一个不能直接使用的类模板,只允许特化。我想用来static_assert显示有意义的错误消息。我不能只输入,static_assert(false, "error");因为false它不依赖于值,即使模板从未使用过,编译器也可能会显示错误消息。
我的解决方案:
template<class>
struct AlwaysFalse : std::false_type{};
#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(sizeof(arg))>::value
template<class T>
struct Foo{
static_assert(DEPENDENT_FALSE(T), "You must use specialization!");
};
template<int i>
struct Bar{
static_assert(DEPENDENT_FALSE(i), "You must use specialization!");
};
Run Code Online (Sandbox Code Playgroud)
但我不确定实现DEPENDENT_FALSE。由于MSVC不把sizeof(arg)作为模板依赖性表达(不像GCC),不过decltype(sizeof(arg)) 是罚款。
有人可以用标准来解释这种行为吗?便携吗?