对不起,如果这是一个骗局。有许多类似的问题,但似乎没有人真正解决这个问题。它们都有点不同。
所以我想要实现的目标:考虑一个模板类X<T>
。现在,我想要一个额外的构造函数为该模板的特定instanciattion延伸,比如指针X<T*>
。我不想为X<T*>
创建一个完整的模板规范,因为X<T*>
应该与通常的模板完全一样(并且该模板是巨大的,因此复制粘贴将是一个代码重复的气味),仅它有一个额外的构造函数。我也不想让X<T*>
继承X<T>
,因为我不想在这两者之间建立子类型关系。
这可能吗?我试过这样的话:
template<T> class X{};
template<T> X<T*>::X(int i){...}
但它没有编译。这有可能吗?
答案 0 :(得分:5)
您可以使用SFINAE:
执行此类操作#include <iostream>
#include <type_traits>
template<class T> class X{
public:
X(int i) {
init();
}
private:
template<class U = T>
typename std::enable_if<std::is_pointer<U>::value>::type init() {
std::cout << "It's a pointer!\n";
}
template<class U = T>
typename std::enable_if<!std::is_pointer<U>::value>::type init() {
std::cout << "It's not a pointer!\n";
}
};
int main() {
X<int> a(1);
X<int*> b(2);
}
哪个输出:
It's not a pointer!
It's a pointer!
你没有重载构造函数,但是你实现了你想要的。
请注意,您需要C ++ 11才能使用此代码。
修改:好的,此代码完全符合您的要求:
#include <iostream>
#include <type_traits>
template<class T> class X{
public:
template<class U = T, class enabler = typename std::enable_if<std::is_pointer<U>::value, T>::type>
X(int i) {
std::cout << "It's a pointer!\n";
}
template<class U = T, class enabler = typename std::enable_if<!std::is_pointer<U>::value, T*>::type>
X() {
std::cout << "It's not a pointer!\n";
}
};
int main() {
X<int> a;
X<int*> b(2);
}
仍然输出与以前相同。请注意,这不是一个很好的设计。根据模板参数设置一些构造函数是奇怪的。这段代码解决了你的问题。
答案 1 :(得分:0)
这是一个使用boost但不需要C ++ 11的解决方案。在任何一种情况下,X
都有一个构造函数,它接受一个参数。当T
是指针时,它所期望的参数是int
。当T
不是指针时,参数是调用者无法访问的类型。
#include <boost/type_traits.hpp>
template < typename T >
class X
{
private:
// Declare a private type that will be used to prevent a single-argument
// constructor from being callable when T is not a pointer.
struct T_must_be_a_pointer;
public:
// Branch at compile-time based on T:
// - If T is a pointer, then declare the X( int ) constructor.
// - If T is not a pointer, then declare X( T_must_be_a_pointer ) constructor.
explicit X( typename boost::mpl::if_< boost::is_pointer< T >,
int,
T_must_be_a_pointer >::type i )
{}
};
int main() {
X<int> a();
// Next line will fail to compile:
// X<int> b(1);
X<int*> c(2);
return 0;
}