我有一个非常有趣的问题:我有两个模板类。一个可以采用任何模板参数,另一个更专业(对于这个玩具问题,我们会说它必须采用浮点数)。
template< class T >
class CanBeAnything{ /*...*/ };
template< class T >
class MustBeFloat{ static_assert(is_floating_point<T>::value, ""); /*...*/ };
现在我有另一个模板类 Foo。Foo 对它的模板参数没有限制,函数 foo 接受 aCanBeAnything
或 aMustBeFloat
的相同类型。我希望在这里使用显式模板实例化,所以我只希望MustBeFloat
当我的模板参数是浮点时存在重载。
最简单的解决方案似乎是专门化 Foo,但我不喜欢跨两个类复制接口的想法。我想出了一个几乎可以工作的 CRTP 解决方案,有一个问题我会在一分钟内提到
/* Traits object to get the value_type out of foo */
template<class FooType>
class FooTraits{};
/* Helper parent class with floating-point only methods */
template<class Derived, bool isFloatingPoint>
class FooSpecialization {}
template<class Derived>
class FooSpecialization<Derived, true>
{
typedef typename FooTraits<Derived>::value_type value_type;
public:
void foo( MustBeFloat<value_type> & x );
};
/* Front-end interface */
template<class T>
class Foo : public FooSpecialization< Foo<T>, is_floating_point<T>::value >
{
typedef FooSpecialization< Foo<T>, is_floating_point<T>::value > Parent;
typedef typename FooTraits< Foo<T> >::value_type value_type;
public:
void foo( CanBeAnything<value_type> & x );
private:
friend class Parent;
};
template<class T>
class FooTraits< Foo<T> >
{ public: typedef T value_type; };
所以这就是问题所在:foo( MustBeFloat<value_type> & )
按原样,通过名称隐藏在子类中隐藏了对的调用,并且编译器给了我“没有对方法 foo 的匹配调用”错误。如果我添加该行using Parent::foo;
以将其关闭,则在实例化 non-floating point 时出现“父类中不存在 foo”错误Foo
,因为该方法不存在那么远。
有任何想法吗?如果有更优雅/更有效的解决方案,我可以抓取整个解决方案。
编辑:澄清一下:我在这里进行显式实例化,这就是为什么我需要该方法仅在我有浮点模板参数时才存在。
template class Foo<int>;
template class Foo<float>;
这会实例化每个类成员,因此依赖于不实例化某些方法的方法是行不通的。
EDIT2:好的,所以我想太多了。这是我要使用的解决方案:
template<class T>
class Foo
{
public:
template<class T2>
void foo( MustBeFloat<T2> & x ){ static_assert( std::is_same<T,T2>::value, ""); /* ... */}
void foo( CanBeAnything<T> & x ){ /* ... */ }
};
template class Foo<int>;
template class Foo<float>;
template void Foo::foo<float>(MustBeFloat<float> &);
这一切都有效。耶!感谢那些帮助我找到这个解决方案并提出其他更具创造性的解决方案的人。