我喜欢提供有用的错误/消息,我也想为我static_assert
的 s 这样做。问题是,它们依赖于模板参数。通常,由于引发的错误,这些参数将在途中或其他地方显示,但它们要么晦涩难懂,要么没有分组,因此它们是有意义的。例子:
template<class T>
struct fake_dependency{
static bool const value = false;
};
template<class T, class Tag>
struct Foo{
Foo(){}
template<class OtherTag>
Foo(Foo<T, OtherTag> const&){
static_assert(fake_dependency<T>::value, "Cannot create Foo<T,Tag> from Foo<T,OtherTag>.");
}
};
int main(){
Foo<int, struct TagA> fA;
Foo<int, struct TagB> fB(fA);
}
MSVC 上的输出:
src\main.cpp(74): error C2338: Cannot create Foo<T,Tag> from Foo<T,OtherTag>.
src\main.cpp(84) : see reference to function template instantiation 'Foo<T,Tag>::Foo<main::TagA>(const Foo<T,main::TagA> &)' being compiled
with
[
T=int,
Tag=main::TagB
]
一个标签在函数模板本身中被提及,另一个在下面的类模板中被提及。不太好。让我们看看GCC 的输出:
prog.cpp: In constructor 'Foo<T, Tag>::Foo(const Foo<T, OtherTag>&) [with OtherTag = main()::TagA, T = int, Tag = main()::TagB]':
prog.cpp:18:32: instantiated from here
prog.cpp:12:5: error: static assertion failed: "Cannot create Foo<T,Tag> from Foo<T,OtherTag>."
好多了,但仍然不是真正的位置static_assert
。现在想象一些更多的参数,或更多的模板,或两者兼而有之。颤抖
解决这个问题的一种方法是使用中间结构,它将两个标签都作为模板参数:
template<class Tag, class OtherTag>
struct static_Foo_assert{
static_assert(fake_dependency<Tag>::value, "Cannot create Foo<T,Tag> from Foo<T,OtherTag>.");
};
template<class T, class Tag>
struct Foo{
Foo(){}
template<class OtherTag>
Foo(Foo<T, OtherTag> const&){
static_Foo_assert<Tag, OtherTag> x;
}
};
现在让我们再次查看输出:
src\main.cpp(70): error C2338: Cannot create Foo<T,Tag> from Foo<T,OtherTag>.
src\main.cpp(79) : see reference to class template instantiation 'static_Foo_assert<Tag,OtherTag>' being compiled
with
[
Tag=main::TagB,
OtherTag=main::TagA
]
好多了!这是GCC 所说的:
prog.cpp: In instantiation of 'static_Foo_assert<main()::TagB, main()::TagA>':
prog.cpp:17:40: instantiated from 'Foo<T, Tag>::Foo(const Foo<T, OtherTag>&) [with OtherTag = main()::TagA, T = int, Tag = main()::TagB]'
prog.cpp:23:32: instantiated from here
prog.cpp:8:5: error: static assertion failed: "Cannot create Foo<T,Tag> from Foo<T,OtherTag>."
看起来还不错。问题:我需要为每个模板创建这样一个结构,因为错误消息static_assert
需要是字符串文字......
现在,对于我的问题:我们能否以某种方式将类型名称直接包含在static_assert
? 喜欢
static_assert(..., "Cannot create Foo<" T "," Tag "> from Foo<" T "," OtherTag ">.");
示例输出:
无法
Foo<int,main::TagA>
从Foo<int,main::TagB>
.
或者,如果这无法实现,我们能否以某种方式使错误消息成为一个额外的模板参数,以使其可以通过?