Xeo*_*Xeo 56 c++ templates static-assert custom-errors c++11
我喜欢提供有用的错误/消息,我也想为我static_assert的.问题是,它们依赖于模板参数.通常情况下,由于引发的错误,这些参数会在途中或其他参数上显示,但它们要么模糊不清,要么不分组,因此它们有意义.例:
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);
}
Run Code Online (Sandbox Code Playgroud)
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
]
Run Code Online (Sandbox Code Playgroud)
函数模板本身提到了一个标记,下面是类模板.不太好.让我们看看海湾合作委员会的成果:
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>."
Run Code Online (Sandbox Code Playgroud)
好多了,但仍然不是真的在哪里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;
}
};
Run Code Online (Sandbox Code Playgroud)
现在让我们再次看到输出:
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
]
Run Code Online (Sandbox Code Playgroud)
好多了!以下是海湾合作委员会的说法:
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>."
Run Code Online (Sandbox Code Playgroud)
看起来不错.问题:我需要为每个模板创建这样的结构,因为错误消息static_assert需要是字符串文字...
现在,对于我的问题:我们能否以某种方式将类型名称直接包含在static_assert?喜欢
static_assert(..., "Cannot create Foo<" T "," Tag "> from Foo<" T "," OtherTag ">.");
Run Code Online (Sandbox Code Playgroud)
示例输出:
不能创建
Foo<int,main::TagA>从Foo<int,main::TagB>.
或者,如果这是不可实现的,我们可以以某种方式使错误消息成为额外的模板参数,以使其可通过吗?
Bob*_*mer 11
template <typename Assertion>
struct AssertValue : AssertionChecker<Assertion::value, Assertion>
{
static_assert(AssertionValue, "Assertion failed <see below for more information>");
static bool const value = Assertion::value;
};
Run Code Online (Sandbox Code Playgroud)
它允许您检查任何::value断言并在失败时转储类型.
// Bad indentation used to show parts
static_assert(
AssertValue<
std::my_check<
T0, decltype(*somethingComplicated), T7::value_type
>
>,
"something horrible happened"
);
Run Code Online (Sandbox Code Playgroud)
其中std::my_check<...>::value是检查的布尔结果
示例的错误消息:
prog.cpp: In instantiation of 'AssertValue<std::is_base_of<IMyInterface, MyBadType> >':
prog.cpp:37:69: instantiated from 'void MyFunction(IteratorType, IteratorType) [with IteratorType = __gnu_cxx::__normal_iterator<MyBadType*, std::vector<MyBadType> >]'
prog.cpp:60:38: instantiated from here
prog.cpp:9:5: error: static assertion failed: "Assertion failed <see below for more information>"
prog.cpp: In function 'void MyFunction(IteratorType, IteratorType) [with IteratorType = __gnu_cxx::__normal_iterator<MyBadType*, std::vector<MyBadType> >]':
prog.cpp:60:38: instantiated from here
prog.cpp:39:5: error: static assertion failed: "iterator passed does not reference IMyInterface items"
Run Code Online (Sandbox Code Playgroud)
如果断言失败,它将打印AssertValue的模板参数,从而打印检查的完整模板扩展.例如,如果您正在检查std::is_base_of它,它将打印完整类型的支票,例如:std::is_base_of<IMyInterface, MyBadType>.然后你就确切地知道在失败的断言中使用了什么类型.
唯一的问题是,这只适用于放置结果的模板::value.然而,type_traits大多数情况下使用此并且是goto标准.
| 归档时间: |
|
| 查看次数: |
11762 次 |
| 最近记录: |