为非指针模板类引发异常?

时间:2012-04-13 14:04:07

标签: c++ templates

我有这个队列类,实际上有几个遭受同样问题 - 如果使用具有冗长拷贝ctor的类型编译,性能将会很差 - 队列在推/弹出期间被锁定且时间越长锁定,争用的机会越大。如果某个开发人员试图用10MB缓冲类编译它(而不是指向它的指针),那么该类将无法编译。

似乎没有简单的方法将模板参数限制为基类或任何其他类型。

我可以使用一些bodge,以便如果参数不是指向类实例的指针,我的类将无法编译吗?

4 个答案:

答案 0 :(得分:5)

您可以通过多种方式完成此操作。正如另一个答案所指出的,你可以使用static_assert(最好是来自C ++ 11 / Boost,虽然你可以roll your own),尽管我建议检查它是否实际上是一个指针,而不仅仅是依赖于它的大小。你可以自己推出或使用existing trait(也可用in C++11),具体取决于您使用的系统:

template <typename T>
struct is_pointer {
  enum { value = 0 };
};

template <typename T>
struct is_pointer<T*> {
  enum { value = 1 };
};

template <typename T>
struct container {
  static_assert(is_pointer<T>::value, "T must be a pointer");
  void push(const T&);
  T pop();
};

struct foo {};

int main() {
  container<foo*> good;
  container<foo> fail;
}

但这提出了更大的观点。如果您的要求是您只是指向事物,那么为什么不首先解释模板参数?例如。制作你的容器:

template <typename T>
struct container {
  void push(const T*);
  T *pop();
};

而不是允许人们首先指定非指针类型?

最后,如果你不想沿着static_assert路走下去,你可以只将容器专门用于指针类型,而不是为非指针实现它,例如:

template <typename T>
struct container;

template <typename T>
struct container<T*> {
  void push(const T*);
  T *pop();
};

struct foo {};

int main() {
  container<foo*> good;
  container<foo> fail;
}

这仍然需要显式地使类型成为指针,仍然导致非指针类型的编译时失败,但是不需要static_assert或确定类型是否是指针的方式。

答案 1 :(得分:2)

“我可以使用一些bodge,以便如果参数不是指向类实例的指针,我的类将无法编译吗?”

不是一个躲闪,但是:

template<class T>
class MyContainer
{
public:
    void AllMemberFunctions( T* in ){}
    void OnlyAcceptTStars( T* in ){}

};

用户定义所持有的类型,并且您的函数只接受或处理指向该类型的指针。

(或者做STL做的事情,假设用户方面有一些情报并忘记了这个问题。)

答案 2 :(得分:0)

使用静态断言的变体(只有谷歌用于许多可能的实现)。像BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(void*))这样的东西应该可以解决问题。

答案 3 :(得分:0)

是的,您可以使用static_assert来完成。例如,

template<int N>
class Queue
{
static_assert(N < size, "N < size violated");
...
};