Car*_*ton 9 c++ inheritance templates sfinae c++11
我有一个Container保存的对象,其类型可以从一些基类的任何组合衍生的(类TypeA,TypeB等).基类Container具有返回指向包含对象的指针的虚方法; nullptr如果包含的对象不是从期望的类派生的,那么它们应该返回.我想根据Container模板参数有选择地覆盖base的方法.我尝试使用SFINAE如下,但它不编译.我想避免专注Container于所有可能的组合,因为可能有很多.
#include <type_traits>
#include <iostream>
using namespace std;
class TypeA {};
class TypeB {};
class TypeAB: public TypeA, public TypeB {};
struct Container_base {
virtual TypeA* get_TypeA() {return nullptr;}
virtual TypeB* get_TypeB() {return nullptr;}
};
template <typename T>
struct Container: public Container_base
{
Container(): ptr(new T()) {}
//Override only if T is derived from TypeA
auto get_TypeA() -> enable_if<is_base_of<TypeA, T>::value, TypeA*>::type
{return ptr;}
//Override only if T is dervied from TypeB
auto get_TypeB() -> enable_if<is_base_of<TypeB, T>::value, TypeB*>::type
{return ptr;}
private:
T* ptr;
};
int main(int argc, char *argv[])
{
Container<TypeA> typea;
Container<TypeB> typeb;
Container<TypeAB> typeab;
cout << typea.get_TypeA() << endl; //valid pointer
cout << typea.get_TypeB() << endl; //nullptr
cout << typeb.get_TypeA() << endl; //nullptr
cout << typeb.get_TypeB() << endl; //valid pointer
cout << typeab.get_TypeA() << endl; //valid pointer
cout << typeab.get_TypeB() << endl; //valid pointer
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...或者您可以将方法更改为更简单的方法:
template <typename T>
struct Container: public Container_base
{
TypeA* get_TypeA() override
{
if constexpr(is_base_of_v<TypeA, T>)
return ptr;
else
return nullptr;
}
...
};
Run Code Online (Sandbox Code Playgroud)
并依靠优化器来抚平任何皱纹。就像用一个函数替换多个return nullptr函数一样(在最终的二进制文件中)。或者,如果您的编译器不支持if constexpr.
编辑:
...或者(如果您坚持使用 SFINAE)以下内容:
template<class B, class T, enable_if_t< is_base_of_v<B, T>>...> B* cast_impl(T* p) { return p; }
template<class B, class T, enable_if_t<!is_base_of_v<B, T>>...> B* cast_impl(T* p) { return nullptr; }
template <typename T>
struct Container: public Container_base
{
...
TypeA* get_TypeA() override { return cast_impl<TypeA>(ptr); }
TypeB* get_TypeB() override { return cast_impl<TypeB>(ptr); }
private:
T* ptr;
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |