2011-04-22 86 views
10

我想定义模板函数,但不允许使用特定类型实例化。请注意,通常所有类型都是允许的,并且通用模板可以工作,我只想禁止使用一些特定的类型。禁止特定函数模板实例化

例如,在下面的代码中,我希望阻止使用double与模板。这实际上并不妨碍实例化,但是由于没有定义函数而导致链接器错误。

template<typename T> 
T convert(char const * in) 
{ return T(); } 

//this way creates a linker error 
template<> 
double convert<double>(char const * in); 

int main() 
{ 
    char const * str = "1234"; 

    int a = convert<int>(str); 
    double b = convert<double>(str); 
} 

该代码只是一个演示,显然转换函数必须做更多的事情。

问题:在上面的代码中,我怎么能产生尝试使用convert<double>实例化时,编译器错误?


我能找到的最接近的相关问题是How to intentionally cause a compile-time error on template instantiation它涉及一个类而不是函数。

我需要这样做的原因是因为我希望阻止的类型实际上会编译并使用通用版本进行操作。然而,这不应该是该功能合同的一部分,并且可能在所有平台/编译器和未来版本中都不支持。因此,我想阻止使用它。

+0

您已经这样做了,是吗? – Nawaz 2011-04-22 11:00:07

+0

不,这会导致关于缺少函数的链接器错误。这个错误不会告诉你问题在哪里,它只会告诉你它在哪个模块中。 – 2011-04-22 11:05:20

+3

你可以使用'static_assert'触发一个编译时错误:'template <> foo (const char *) {static_assert(false,“不允许”); }' – evnu 2011-04-22 11:10:38

回答

3

我会用你的函数调用中的静态断言函数实例化过程中创造适当的失败:

template<typename T> 
class is_double{ static const int value = false; } 

template<> 
class is_double<double>{ static const int value = true; } 

template<typename T> 
T convert(const char *argument){ 
    BOOST_STATIC_ASSERT(!is_double<T>::value); 
    //rest of code 
} 

而且应该在一个函数内工作。

+0

应该是'static bool const value'。 :) – Xeo 2011-04-22 11:50:33

+0

@Xeo谢谢,修正。 – wheaties 2011-04-22 12:57:03

+0

啊是的。我觉得很愚蠢,因为我在很多地方使用静态断言,不知何故它在这里逃脱了我的想法。 – 2011-04-22 13:18:17

1

你可以使用一个仿函数,而不是一个功能:

template<typename T> 
struct convert { 
    T operator()(char const * in) const { return T(); } 
}; 
template<> struct convert<double>; 

int main() 
{ 
    char const * str = "1234"; 

    int a = convert<int>()(str); 
    double b = convert<double>()(str); // error in this line 

    return 0; 
} 

这将使你在实例化点错误。

通过添加辅助函数,你会得到想要的行为:

template<typename T> 
struct convert_helper { 
    T operator()(char const * in) const { return T(); } 
}; 
template<> struct convert_helper<double>; 

template<typename T> 
T convert(char const * in) { return convert_helper<T>()(in); } 

int main() 
{ 
    char const * str = "1234"; 

    int a = convert<int>(str); 
    double b = convert<double>(str); 

    return 0; 
} 
+0

这也是一个不错的选择,因为我基本上已经有其他原因的第二个方案。 – 2011-04-22 13:19:38

1

如果你不想靠static_assert或使代码移植前的C++ 0x,使用此:

template<class T> 
void func(){ 
    typedef char ERROR_in_the_matrix[std::is_same<T,double>::value? -1 : 1]; 
} 

int main(){ 
    func<int>(); // no error 
    func<double>(); // error: negative subscript 
} 
+0

我不认为'std:is_same'在C++ 11之前是可用的(或者是C++ 0x,因为它在这里) – Pharap 2014-12-15 00:16:59

0

考虑Boost disable_ifBoost TypeTraits

看看How can I write a function template for all types with a particular type trait?

这是一个例子:

#include <boost/type_traits.hpp> 
#include <boost/utility/enable_if.hpp> 

template<typename T> 
T convert(char const * in, 
      typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0) 
{ return T(); } 


int main() 
{ 
    char const * str = "1234"; 

    int a = convert<int>(str); 
    double b = convert<double>(str); 
    return 0; 
} 


这是该字符串的编译错误

double b = convert<double>(str); 

1>。\ simple_no_stlport。't convert(const char *,boost :: disable_if,T> :: type *)'1>。\ simple_no_stlport.cpp(5)cpp(14):error C2770:无效显式模板 参数):请参阅 “转换”声明