テンプレートのタイプに基づいて、テンプレートクラスのメンバー関数を特殊化しようとしています。特に、ポリモーフィックタイプに基づいた専門分野が欲しいです。私は構文に苦労してきました。これが明らかにエラーを生成する私の試みです:宣言の2つ以上のデータ型doSomething()
class Base {};
class Derived : public Base {};
template<typename T>
class MyClass
{
public:
void doSomething();
};
template<>
template<typename T>
typename std::enable_if<std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// Do something with Derived type
}
template<>
template<typename T>
typename std::enable_if<std::is_base_of<Base, T>::value &&
!std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// So something with Base type
}
template<>
template<typename T>
typename std::enable_if<!std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// Do something with all other types
}
コンパイルは与える..
error: two or more data types in declaration of 'doSomething'
ところで、私はコンパイルするために以下を取得しましたが、特殊化は実行時に期待どおりに機能しませんでした。基本型と派生型は、特殊化されていないバージョンのを通過することになりdoSomething()
ます。
class Base {};
class Derived : public base {};
template<typename T>
class MyClass
{
public:
void doSomething()
{
// Do something for non-specialized types
}
};
template<>
void MyClass<Derived>::doSomething()
{
// Do something with Derived type
}
template<>
void MyClass<Base>::doSomething()
{
// So something with Base type
}
正しい構文は何でしょうか?
doSomething
テンプレートではないという理由だけで専門化することはできません。MyClass
はテンプレートであり、クラスを特殊化できますdoSomething
。各特殊化には1つあります。それが望ましくない場合は、doSomething
テンプレートをオーバーロードする必要があります。SFINAEを機能させるには、SFINAEチェックをdoSomething
パラメーターではなくテンプレートパラメーターで実行する必要がありMyClass
ます。最後に、あなたのチェックは間違っています。
だからここに私のバージョンがあります:
template<class T> struct MyClass
{
template <class U = T>
auto foo() -> std::enable_if_t<std::is_base_of_v<Base, U>
&& !std::is_base_of_v<Derived, U>>
{
foo_base();
}
template <class U = T>
auto foo() -> std::enable_if_t<std::is_base_of_v<Derived, U>>
{
foo_derived();
}
template <class U = T>
auto foo() -> std::enable_if_t<!std::is_base_of_v<Base, U>>
{
foo_else();
}
};
そして、ここに一連のテストがあります:
class Base {};
class Derived : public Base {};
class A : Base {};
class B : Derived {};
class X {};
auto test()
{
MyClass<Base>{}.foo(); // foo_base
MyClass<Derived>{}.foo(); // foo_derived
MyClass<A>{}.foo(); // foo_base
MyClass<B>{}.foo(); // foo_derived
MyClass<X>{}.foo(); // foo_else
}
そしてもちろん、私はC ++ 17のクリーンなソリューションについて言及する必要があります。
template<class T> struct MyClass
{
auto foo()
{
if constexpr (std::is_base_of_v<Derived, T>)
foo_derived();
else if constexpr (std::is_base_of_v<Base, T>)
foo_base();
else
foo_else();
}
};
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加