27

static_assertテンプレート パラメーター値の望ましくない値にフラグを付けるために使用してきました (使用されていることがわかりました)。ただし、私が遭遇したすべてのケースで、SFINAE を介してこれらの望ましくない値を無効にする方が適切でエレガントなようです。

例えば:

template<typename T,
         class = std::enable_if<std::is_floating_point<T>::value>::type>
struct Foo { ... };

それ以外の:

template<typename T>
struct Foo
{
    static_assert(std::is_floating_point<T>::value,
                  "Foo<T>: T must be floating point :-(");
    ...
};

私の質問: static_assertSFINAE の代わりに使用する必要があるのはなぜですか?

編集:

これまでに学んだことは次のとおりだと思います。

1. SFINAE は多機能で強力ですが、潜在的に非常に複雑なツールであり、関数のオーバーロードの解決 (唯一の目的と見​​なす人もいます) など、多くのタスクに使用できます。

2. SFINAE は、その定義ではなく (クラスまたは関数の)宣言static_assertに現れることを除いて、可能な限りどこでも比較的単純な方法で使用できます (または、クラスの前方宣言に aを挿入することは可能ですか?) . これにより、より逐語的になり、コードがより明確になります。ただし、SFINAE は複雑なため、単純な.static_assertstatic_assert

3.一方static_assert、より明確なコンパイラ エラー メッセージの利点があり、これが両方の主な目的と見なされているようです。

4

4 に答える 4

19

static_assert別のオーバーロードを使用する場合、およびそれらのいずれもそのようなパラメーターに適合しない場合は、SFINAE を使用します。

于 2012-08-16T10:07:38.817 に答える
14

static_assertコンパイルが失敗します。SFINAE を使用すると、考えられる過負荷を 1 つ取り除くことができます。

于 2012-08-16T10:02:33.393 に答える
9

浮動小数点型であるstatic_assertことを強制したい場合は、正しい選択だと思います。Tこの方法は、SFINAE ソリューションよりも明確に意図を示します。

于 2012-08-16T10:43:16.093 に答える
6

1つは、SFINAEを使用すると、元々はより悪い一致であり、考慮されない別の過負荷が選択される可能性があります。

そして、他の過負荷があるが、それらのどれも実行可能ではないという状況では、あなたはこのようないくつかの素晴らしいものを手に入れます:

#include <type_traits>

void f(int){}
void f(bool){}
void f(char){}
void f(float){}
void f(long){}
void f(double){}
void f(short){}
void f(unsigned){}
void f(void*){}
void f(void (*)()){}

template<class C, class T = int>
using EnableIf = typename std::enable_if<C::value, T>::type;

template<class T>
struct sfinae_false : std::false_type{};

template<class T> 
void f(T&&, EnableIf<sfinae_false<T>> = 0){}

int main(){ struct X{}; f(X()); }

出力:

source.cpp: In function 'int main()':
source.cpp:23:30: error: no matching function for call to 'f(main()::X)'
source.cpp:23:30: note: candidates are:
source.cpp:3:6: note: void f(int)
source.cpp:3:6: note:   no known conversion for argument 1 from 'main()::X' to 'int'
source.cpp:4:6: note: void f(bool)
source.cpp:4:6: note:   no known conversion for argument 1 from 'main()::X' to 'bool'
source.cpp:5:6: note: void f(char)
source.cpp:5:6: note:   no known conversion for argument 1 from 'main()::X' to 'char'
source.cpp:6:6: note: void f(float)
source.cpp:6:6: note:   no known conversion for argument 1 from 'main()::X' to 'float'
source.cpp:7:6: note: void f(long int)
source.cpp:7:6: note:   no known conversion for argument 1 from 'main()::X' to 'long int'
source.cpp:8:6: note: void f(double)
source.cpp:8:6: note:   no known conversion for argument 1 from 'main()::X' to 'double'
source.cpp:9:6: note: void f(short int)
source.cpp:9:6: note:   no known conversion for argument 1 from 'main()::X' to 'short int'
source.cpp:10:6: note: void f(unsigned int)
source.cpp:10:6: note:   no known conversion for argument 1 from 'main()::X' to 'unsigned int'
source.cpp:11:6: note: void f(void*)
source.cpp:11:6: note:   no known conversion for argument 1 from 'main()::X' to 'void*'
source.cpp:12:6: note: void f(void (*)())
source.cpp:12:6: note:   no known conversion for argument 1 from 'main()::X' to 'void (*)()'
source.cpp:21:6: note: template<class T> void f(T&&, EnableIf<sfinae_false<T> >)
source.cpp:21:6: note:   template argument deduction/substitution failed:
于 2012-08-16T10:09:37.990 に答える