【发布时间】:2014-05-01 17:24:45
【问题描述】:
我有一个非常有趣的问题:我有两个模板类。一个可以采用任何模板参数,另一个更专业(对于这个玩具问题,我们会说它必须采用浮点数)。
template< class T >
class CanBeAnything{ /*...*/ };
template< class T >
class MustBeFloat{ static_assert(is_floating_point<T>::value, ""); /*...*/ };
现在我有了另一个模板类 Foo。 Foo 对它的模板参数没有任何限制,函数 foo 采用相同类型的 CanBeAnything 或 MustBeFloat。我希望在这里使用显式模板实例化,所以我只希望在我的模板参数为浮点时存在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; 将其关闭,则在实例化非浮点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> &);
这一切都有效。耶!感谢那些帮助我找到这个解决方案并提出其他更具创造性的解决方案的人。
【问题讨论】:
-
澄清一下:当 value_type 是浮点数时,您希望 Foo 同时具有 MustBeFloat 和 CanBeAnything 版本的 foo() 吗?但是,如果 value_type 不是浮点数,那么它应该只有 CanBeAnything 版本的 foo() ?
-
@qeadz 这就是意图,是的。抱歉,如果从描述中不清楚。
-
好的。使用“foo”之类的例子总是很愚蠢,所以这个建议可能行不通。如果您只需要在 value_type 是浮点数时出现 foo() 的专用版本,那么根本不从 FooSpecialization 派生如何。只需在 Foo 类中有多个版本的函数 foo()。使用 enable_if 仅根据 value_type 编译您想要的版本。如果更清楚的话,我可以用代码 sn-p 在答案中输入它。
-
...老实说,这是我第一次听说使用“enable_if”。我做了一个模型,这正是我需要的。如果您想将其复制粘贴为实际答案,我会将其标记为正确。
-
您的问题已解决,因此我现在不太愿意花时间处理这些问题。如果有人发布了更详细的答案,请务必将其标记为正确 - 高质量的回复需要时间,并且总体上对这个网站有好处(我只是懒得一直这样做)。
标签: c++ templates overloading template-specialization name-hiding