启用if / else类成员模板实例化

时间:2016-05-25 16:00:47

标签: c++ templates c++11

任何人都可以告诉我如何基于来自预定义基本集的不同派生类启用if / else类成员模板吗?让我使用以下示例:

enum class Type {
  TYPEA,
  TYPEB
};

// Predefined in libraries.
class BaseA {...};
class BaseB {...};

class Foo {
  template <typename Derived, Type type>
  void foo();
};

// User-derived
class DerivedA : public BaseA {};
class DerivedB : public BaseB {};

通常我们需要两个模板类型名来调用成员foo。

Foo obj;
obj.foo<DerivedA, Type::TypeA>()
obj.foo<DerivedB, Type::TypeB>();

然而,这种原生方法似乎很长,因为第二个模板参数Type::TypeAType::TypeB显然可以由编译器通过第一个参数DerivedADerivedB推断出来,如果它们正确地从预定义的基础派生。我注意到c ++ 11提供了is_base_of模板,但我不知道如何在我的情况下使用它。更具体地说,以下是预期的解决方案:

obj.foo<DerivedA>();  // Automatically deduce type = Type::TypeA
obj.foo<DerivedB>();  // Automatically deduce type = Type::TypeB

如果编译无法从第一个类型名推导出Type,那么它应该回到正常声明obj.foo<MyClass, MyType>,其中MyTypeType::TypeA或者Type::TypeB

2 个答案:

答案 0 :(得分:1)

听起来你只想要一个默认的模板参数:

class Foo {
  template <typename Derived, Type type = get_type_from<Derived>::value>
  void foo();
};

get_type_from<>是根据您实际找出Type的方式稍后填写的元函数。

答案 1 :(得分:0)

template<Type t>
using etype_tag = std::integral_constant<Type, t>;

template<class T>
struct tag_t {
  using type=T;
  template<class D,
    std::enable_if_t<std::is_base_of<T, D>::value, int>* =nullptr
  >
  constexpr tag_t( tag_t<D> ) {}
  constexpr tag_t() = default;
  constexpr tag_t(tag_t const&) = default;
};

template<class T>
constexpr tag_t<T> tag{};


constexpr etype_tag<Type::TYPEA> get_etype( tag_t<BaseA> ) { return {}; }
constexpr etype_tag<Type::TYPEB> get_etype( tag_t<BaseB> ) { return {}; }

template<class T>
constexpr decltype( get_etype( tag<T> ) ) etype{};

现在etype<Bob>是你想要的编译时常量整数常量。

class Foo {
  template <typename Derived, Type type=etype<Derived>>
  void foo();
};

使第二个参数(通常)多余。

您可以在声明get_etype的命名空间或etype的命名空间中,或在您正在扩展的类型的命名空间中tag_t扩展get_etype etype <div class="demo" ng-app="MyApp"> <md-content class="md-padding" flex-gt-xs="50"> <div layout="column" layout-align="center center"> <md-card> <md-card-title> ... </md-card-title> </md-card> <md-button class="md-fab" aria-label="Eat cake"> <md-icon md-svg-src="img/icons/cake.svg"></md-icon> </md-button> </div> </md-content> </div> 1}}使用,feed将自动获得支持(假设它在扩展可见的上下文中使用:该要求的失败会导致程序生成错误。)

Live example