我有这个队列类,实际上有几个遭受同样问题 - 如果使用具有冗长拷贝ctor的类型编译,性能将会很差 - 队列在推/弹出期间被锁定且时间越长锁定,争用的机会越大。如果某个开发人员试图用10MB缓冲类编译它(而不是指向它的指针),那么该类将无法编译。
似乎没有简单的方法将模板参数限制为基类或任何其他类型。
我可以使用一些bodge,以便如果参数不是指向类实例的指针,我的类将无法编译吗?
答案 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");
...
};