有人能告诉我如何基于预定义基组的不同派生类启用if/ set类成员模板吗?让我使用以下示例:
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::TypeA
和Type::TypeB
来自预定义的基,那么编译器显然可以通过第一个参数DerivedA
和DerivedB
推导它们。我注意到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>
,其中MyType
是Type::TypeA
或Type::TypeB
。
发布于 2016-05-25 08:48:51
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
的名称空间中,或者在tag_t
的名称空间中,或者在您要使用的扩展get_etype
类型的名称空间中,使用更多重载来扩展get_etype
,并且etype
将自动获得支持(假设它是在可见扩展的上下文中使用的:该需求的失败使您的程序格式不正确)。
发布于 2016-05-25 08:24:00
听起来你只是想要一个默认的模板参数:
class Foo {
template <typename Derived, Type type = get_type_from<Derived>::value>
void foo();
};
其中get_type_from<>
是一个元函数,稍后将根据您实际如何计算Type
来填充。
https://stackoverflow.com/questions/37442340
复制