1

对不起,如果这是一个骗局。有许多类似的问题,但似乎没有一个真正解决这个问题。他们都有点不同。

所以我想要实现:考虑一个模板类X<T>。现在,我希望为该模板的特定实例存在一个额外的构造函数,比如说指针X<T*>。我不想创建一个完整的模板规范X<T*>,因为X<T*>它应该和通常的模板完全一样(而且那个模板很大,所以复制粘贴会是一种代码重复的味道),只是它有一个额外的构造函数。我也不想X<T*>继承自,X<T>因为我不想在这两者之间建立子类型关系。这可能吗?我试过这样:

template<T> class X{};

template<T> X<T*>::X(int i){...}

但它不编译。这有可能吗?

4

2 回答 2

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);
}

仍然输出与以前相同。请注意,这不是一个很好的设计。根据您的模板参数有一些构造函数很奇怪。这段代码虽然解决了你的问题。

于 2012-06-15T14:22:06.890 回答
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;
}
于 2012-06-15T15:17:14.117 回答