具体的なクラスがテンプレートパラメータに基づいて実装するインターフェイスを選択しようとしています。以下の簡単な例では、異なる名前のメソッドを持つ2つのインタフェースがあります。Implementation
クラスは、テンプレートのパラメータに応じてメソッドの実装を提供する必要があります。SFINAEを使用して実装するインターフェイスを選択する
IntType
を使用する場合は、IntInterface
(getInt()
とsetInt(int)
)を実装する必要があります。 DoubleType
を使用する場合は、DoubleInterface
(getDouble()
とsetDouble(double)
)を実装する必要があります。
これを達成するために、使用するインターフェイス(InterfaceType
)を決定するtraitsクラスを作成しましたが、SFINAEに使用する別のパラメータもあります。
考えてみましょう。 MyTypeTrait<Type>::MyTypeInt
であるが、関連形質クラスはMyTypeInt
の定義を持たず、コンパイラはこの可能性のあるオーバーロード(例えばsetInt()
など)をスローし、別のものを使用する。それはダミーが蹴られるべき場所です - 彼らは異なった議論を持ち、彼らはバーチャルではありません。
ただし、動作しません。下記のコンパイラエラーを参照してください。
私はVisual Studio 2013(VC12)を使用しています。
struct IntInterface
{
virtual int getInt() const = 0;
virtual void setInt(int value) = 0;
};
struct DoubleInterface
{
virtual double getDouble() const = 0;
virtual void setDouble(double value) = 0;
};
const int IntType = 0;
const int DoubleType = 1;
template <int Type>
struct MyTypeTrait;
template <>
struct MyTypeTrait<IntType>
{
using MyTypeInt = int;
using InterfaceType = IntInterface;
};
template <>
struct MyTypeTrait<DoubleType>
{
using MyTypeDouble = double;
using InterfaceType = DoubleInterface;
};
template <int Type>
struct Implementation : public MyTypeTrait<Type>::InterfaceType
{
// Actual interface implementation for the case of IntType
virtual typename MyTypeTrait<Type>::MyTypeInt getInt() const override { return 0; }
virtual void setInt(typename MyTypeTrait<Type>::MyTypeInt value) override {}
// Dummys for SFINAE - to be used in the case of DoubleType
typename int getInt(int) const { return 0; }
void setInt() {}
// Actual interface implementation for the case of DoubleType
virtual typename MyTypeTrait<Type>::MyTypeDouble getDouble() const override { return 0.0; }
virtual void setDouble(typename MyTypeTrait<Type>::MyTypeDouble value) override {}
// Dummys for SFINAE - to be used in the case of IntType
typename double getDouble(int) const { return 0.0; }
void setDouble() {}
};
int main(int argc, char* argv[])
{
Implementation<IntType> myInt;
Implementation<DoubleType> myDouble;
}
コンパイラエラー:
1>c++-tests.cpp(50): error C2039: 'MyTypeDouble' : is not a member of 'MyTypeTrait<0>'
1> c++-tests.cpp(26) : see declaration of 'MyTypeTrait<0>'
1> c++-tests.cpp(61) : see reference to class template instantiation 'Implementation<0>' being compiled
1>c++-tests.cpp(50): error C2146: syntax error : missing ';' before identifier 'getDouble'
1>c++-tests.cpp(50): error C2433: 'Implementation<0>::MyTypeDouble' : 'virtual' not permitted on data declarations
1>c++-tests.cpp(50): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c++-tests.cpp(50): warning C4183: 'getDouble': missing return type; assumed to be a member function returning 'int'
1>c++-tests.cpp(51): error C2039: 'MyTypeDouble' : is not a member of 'MyTypeTrait<0>'
1> c++-tests.cpp(26) : see declaration of 'MyTypeTrait<0>'
1>c++-tests.cpp(51): error C2061: syntax error : identifier 'MyTypeDouble'
1>c++-tests.cpp(55): error C2535: 'void Implementation<0>::setDouble(void)' : member function already defined or declared
1> c++-tests.cpp(51) : see declaration of 'Implementation<0>::setDouble'
1>c++-tests.cpp(50): error C3668: 'Implementation<0>::getDouble' : method with override specifier 'override' did not override any base class methods
1>c++-tests.cpp(51): error C3668: 'Implementation<0>::setDouble' : method with override specifier 'override' did not override any base class methods
1>c++-tests.cpp(42): error C2039: 'MyTypeInt' : is not a member of 'MyTypeTrait<1>'
1> c++-tests.cpp(33) : see declaration of 'MyTypeTrait<1>'
1> c++-tests.cpp(62) : see reference to class template instantiation 'Implementation<1>' being compiled
1>c++-tests.cpp(42): error C2146: syntax error : missing ';' before identifier 'getInt'
1>c++-tests.cpp(42): error C2433: 'Implementation<1>::MyTypeInt' : 'virtual' not permitted on data declarations
1>c++-tests.cpp(42): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c++-tests.cpp(42): warning C4183: 'getInt': missing return type; assumed to be a member function returning 'int'
1>c++-tests.cpp(43): error C2039: 'MyTypeInt' : is not a member of 'MyTypeTrait<1>'
1> c++-tests.cpp(33) : see declaration of 'MyTypeTrait<1>'
1>c++-tests.cpp(43): error C2061: syntax error : identifier 'MyTypeInt'
1>c++-tests.cpp(47): error C2535: 'void Implementation<1>::setInt(void)' : member function already defined or declared
1> c++-tests.cpp(43) : see declaration of 'Implementation<1>::setInt'
1>c++-tests.cpp(42): error C3668: 'Implementation<1>::getInt' : method with override specifier 'override' did not override any base class methods
1>c++-tests.cpp(43): error C3668: 'Implementation<1>::setInt' : method with override specifier 'override' did not override any base class methods
このコンパイラは、C++ 11をサポートしていますか? –
コンパイラが古すぎて、現在のC++標準をサポートできません。 –
@RichardHodges MSVC2013はC++ 11のサポートを主張しています。それは不安定で、SFINAEはそれが最悪のものの1つです。 – jaggedSpire