1

我想为两个(或更多)不同的实现使用相同的类模板名称,具体取决于typename T参数的某些属性。

我的第一次尝试:

template< typename T > class invert;

template< typename port >
class invert< port > : public port {
public:
   static int n_pins(){ return port::n_pins(); }
   static void set( unsigned int x ){ port_out::set( x ^ 0xFFFF ); }
};

template< typename pin >
class invert< pin > : public pin {
public:
   static void set( bool x ){ pin::set( ! x ); }
};

我希望第一个专业会被选中,当T::n_pins()可用时选择第一个特化,但编译器抱怨我的特化没有特化任何模板参数。

还有另一种方法可以让我专注于typename论点的属性吗?

4

1 回答 1

3

为什么你的代码不起作用

模板参数portpin只是形式参数。例如,对于常规功能,您是否期望

void foo(int x) { /* bla */ }

void foo(int y) { /* meh */ }

彼此不同?实际上,您可以仅通过签名在标头中简单地声明此类函数void foo(int)。要重载函数,您需要提供不同的参数。

使用模板参数,它的工作原理完全相同

template<typename port> class invert { /* bla */ };

template<typename pin> class invert { /* bla */ }; 

具有相同的模板签名,实际上可以template<typename> class invert;在标头内声明。

在这里,类比不成立,因为类模板不会重载,但必须专门化。这意味着invert无论您在类实现本身中编写什么内容,您的两个版本的参数结构都需要“足够不同”。

如何修复它

为了得到你想要的,你实际上至少需要专门化其中一个模板。执行此操作的典型方法已在此处解释过,并且是定义一个特征类并在编译时使用 SFINAE 进行选择:

template <typename T>
class has_n_pins
{
    typedef char one;
    typedef long two;

    template <typename C> static one test( typeof(&C::n_pins) ) ;
    template <typename C> static two test(...);


public:
    enum { value = sizeof(test<T>(0)) == sizeof(char) };
};

template<typename T, bool = has_n_pins<T>::value >
class invert: public T
{
    // your current port implementation
};

// specialization for types T that don't have a n_pins() member function
template<typename T>
class invert<T, false>: public T
{
     // your current pin implementation
};

现在有两个专业化:(invert<T, true>所有Tn_pins())和invert<T, false>(所有T没有)。编译器现在可以根据您实际提供的模板参数选择合适的参数。

于 2013-06-08T21:23:52.753 回答