C++ 为特定模板特化添加重载方法

标签 c++ templates overloading template-specialization name-hiding

我有一个非常有趣的问题:我有两个模板类。一个可以采用任何模板参数,另一个更专业(对于这个玩具问题,我们会说它必须采用 float )。

template< class T >
class CanBeAnything{ /*...*/ };

template< class T >
class MustBeFloat{ static_assert(is_floating_point<T>::value, ""); /*...*/ };

现在我有了另一个模板类 Foo。 Foo 对其模板参数没有限制,函数 foo 接受 CanBeAnythingMustBeFloat同类型的。我希望在这里使用显式模板实例化,所以我只想要 MustBeFloat当我的模板参数是 float 时重载存在。

最简单的解决方案似乎是专门化 Foo,但我不喜欢在两个类之间复制接口(interface)的想法。我想出了一个几乎可以工作的 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;为了降低它,在实例化非 float 时出现“父类中不存在 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> &);

一切正常。耶!感谢帮助我找到这个解决方案并提出其他更有创意的解决方案的人。

最佳答案

好的。所以我还没有完全测试这个,但如果你有回复,那么我会评论或修改这个建议。但这里有一些示例代码,应该在简化测试用例中编译成 foo() 版本,并使其特定于父类使用的类型:

template< typename T >
class TestClass
{
  typedef struct PlaceholderType {};

public:
  template< typename T2 >
  typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Float"; }

  template< typename T2 >
  typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && !std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Non-float"; }
};


int main(int argc, char* argv[])
{
  TestClass<int> intClass; // should only have the MyFunc(int) version available
  TestClass<float> floatClass; // should only have the MyFunc(float) version available

  intClass.MyFunc(5); // should output "Non-float"
  intClass.MyFunc(5.0f); // should output "Non-float"
  floatClass.MyFunc(2.0f); // should output "Float"
  floatClass.MyFunc(2); // should output "Float"
}

关于C++ 为特定模板特化添加重载方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23412952/

相关文章:

c++ - 如何在 C++ 中将以秒为单位的字符串转换为时间

c++ - 模板参数包如何具有其他尾随参数?

c++ - 包含模板的 (sdk) 类的前向声明

c++ - 没有 <> 的模板特化

c++ - 全局函数模板重载和 const 参数

types - Kotlin赋值运算符重载和类型转换

c++ - 如何调用 'call by value '和 'call by reference'重载函数?

c++ - C++ 类中的线程

c++ - 我怎么能在 VC 2008 中删除 "error C4335: Mac file format detected"

c++ - 在迭代器中取消引用类指针函数