私は役立つエラーやメッセージを提供するのが好きで、自分のためにもそうしたいと思っています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);
}
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
]
1 つのタグは関数テンプレート自体に記載されており、もう 1 つのタグはクラス テンプレートの下に記載されています。あまり良くない。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
。そして、いくつかのパラメータ、テンプレート、またはその両方を想像してみてください。震える
これを回避する 1 つの方法は、両方のタグをテンプレート パラメーターとして受け取る中間構造体を使用することです。
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>
。
または、それが達成できない場合は、何とかしてエラー メッセージを追加のテンプレート パラメーターにして、問題ないようにすることはできますか?