2009-11-01 62 views
1

我希望能够在我调用foo的构造函数时使编译器大声呼叫,而类 不是从_base *派生的。目前的代码只允许foo < _base *>本身。任何 简单的解决方案?通过基类实现C++模板特化

class _base 
{ 
public: 
    // ... 
}; 

class _derived: public _base 
{ 
public: 
    // ... 
}; 

template <typename T> 
class foo 
{ 
public: 
    foo()  { void TEMPLATE_ERROR; } 
}; 

template <> foo<_base*>::foo() 
{ 
    // this is the only constructor 
} 

主代码:

foo<_base*> a; // should work 
foo<_derived*> b; // should work (but doesnt) 
foo<int*>  c; // should not work (and infact doesnt) 

回答

3

没有加速,你可以使用类似以下,以确定是否一个指针到类型可以隐式转换为另一个指针到类型:

template <class Derived, class Base> 
struct IsConvertible 
{ 
    template <class T> 
    static char test(T*); 

    template <class T> 
    static double test(...); 

    static const bool value = sizeof(test<Base>(static_cast<Derived*>(0))) == 1; 
}; 

要使它在触发编译期错误时间,现在可以在表达式中使用value,该表达式如果为false,则会导致错误,例如typedef负大小的数组。

template <typename T> 
class foo 
{ 
public: 
    foo() 
    { 
     typedef T assert_at_compile_time[IsConvertible<T, _base>::value ? 1 : -1]; 
    } 
}; 
+0

aaah,谢谢。我努力想通过自己潜入助推器,但我偶然发现了很多代码纠缠,所以我不得不撤退。但是,这正是我正在寻找的东西,谢谢。 – 2009-11-02 08:28:25

+1

如果您想要了解更多信息,请参阅Andrei Alexandrescu的“Modern C++ Design:Generic Programming and Design Patterns Applied”一书。 – 2009-11-02 14:59:27

+0

+1这是一个非常好的。并感谢您的书推荐! – 2009-11-03 00:30:00

4

使用SFINAE(通过enable_if)和Boost的is_convertible type trait

template <typename T, typename Enabled = void> 
class foo 
{ 
private: 
    foo(); // Constructor declared private and not implemented. 
}; 

template <typename T> 
class foo<T, typename enable_if<is_convertible<T, _base*> >::type> 
{ 
public: 
    foo() { /* regular code */ } 
}; 

(本机上安装未经测试,还没有得到升压)

+0

Thanx,我读通过链接,他们引发了一些想法。应该是一个很好的解决方案,但我目前还没有使用boost。 – 2009-11-01 18:33:37

+0

Boost的美妙之处在于您只能使用它的一部分 - 特别是大多数头文件可以复制粘贴到项目目录或系统包含目录中。 – 2009-11-01 21:10:21

1

我知道你没有在你的项目中使用boost,但也许你可以复制粘贴它的一些部分。

我发现了一个简单的解决问题的方法使用boost:

template <typename T> 
class foo 
{ 
public: 
    foo() { 
     BOOST_STATIC_ASSERT((boost::is_convertible<T,_base*>::value)); 
    } 
}; 

它不需要额外的模板参数,也没有必要为模板特殊化。我用boost 1.40进行了测试。