半通用功能

时间:2010-03-28 20:51:26

标签: c++ generics function

我有一堆重载函数可以处理某些数据类型,例如int,double和strings。这些函数中的大多数执行相同的操作,其中仅允许一组特定的数据类型。这意味着我无法创建一个简单的通用模板函数,因为我失去了类型安全性(并且可能会导致函数内的验证运行时问题)。

是否可以创建“半通用编译时类型安全功能”?如果是这样,怎么样?如果没有,这是否会出现在C ++ 0x中?

一个(无效的)想法;

template <typename T, restrict: int, std::string >
void foo(T bar);
...
foo((int)0); // OK
foo((std::string)"foobar"); // OK
foo((double)0.0); // Compile Error

注意:我意识到我可以创建一个具有重载构造函数和赋值运算符的类,并将该类的变量传递给函数。

5 个答案:

答案 0 :(得分:5)

使用sfinae

template<typename> struct restrict { };
template<> struct restrict<string> { typedef void type; };
template<> struct restrict<int> { typedef void type; };

template <typename T>
typename restrict<T>::type foo(T bar);

foo只能接受string的{​​{1}}或int。如果调用T,则不会发生硬编译时错误,而是如果有另一个接受该参数的函数,则会改为使用该函数。

答案 1 :(得分:1)

你可以创建一个永远不会暴露在外面的“私人”模板化功能,并从你的“安全”重载中调用它。

顺便说一句,通常直接暴露模板化版本存在问题:如果传递的类型不合适,将发出编译错误(除非您知道您的算法可能会暴露某些数据类型的细微错误)

答案 2 :(得分:0)

也许有点丑陋的解决方案,但是仿函数可能是一个选择:

class foo {
   void operator()(double); // disable double type
public:
   template<typename T>
   void operator ()(T bar) {
      // do something
   }
};

void test() {
   foo()(3); // compiles
   foo()(2.3); // error
}

编辑:我反转我的解决方案

class foo {
   template<typename T>
   void operator ()(T bar, void* dummy) {
     // do something
   }
public:
   // `int` is allowed
   void operator ()(int i) {
      operator ()(i, 0);
   }
};

foo()(2.3); // unfortunately, compiles
foo()(3); // compiles
foo()("hi"); // error

答案 3 :(得分:0)

您可以使用要允许的“受限”类型的模板特化。对于所有其他类型,您不提供模板专门化,因此将使用通用的“基本”模板。你可以使用类似BOOST_STATIC_ASSERT的东西来抛出编译错误。

这里有一些伪代码来澄清我的想法:

template <typename T>
void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);}

template<> // specialized for double
void foo(double bar) {do_something_useful(bar);};

答案 4 :(得分:0)

要列出任意类型的选择,我想您可以使用类型列表。请参阅last part of my earlier answer

用法可能类似于:

//TODO: enhance typelist declarations to hide the recursiveness
typedef t_list<std::string, t_list<int> > good_for_foo; 

template <class T>
typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t);