6

我通常声明我的类和模板,然后定义它们的方法(当然是在同一个头文件中)。我只是觉得这样更容易阅读。好吧,我遇到了一个案例,我无法确定在类外定义中使用的工作类型签名。这是我正在做的一个简化示例,它说明了问题:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      , enable_if< is_iterator<Iterator> >
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  , WHAT_GOES_HERE?
  >
Foo<T>::Foo(U f, U l)
{ ... }

我在WHAT_GOES_HERE插槽中尝试了很多方法来尝试获得匹配的签名,但我一直失败。我需要 enable_if 来区分一个传入两个 T 类型对象的情况,以及一个传入一对迭代器的情况。如果模板化的构造函数是在主模板中定义的,则代码可以正常工作,这就是代码当前的工作方式,但我更愿意将定义移到声明之外。

编辑:我应该提一下,我不能只在定义中重复使用 enable_if<...> ,因为 enable_if<...> 为其类型分配了一个默认值,而你不能在不是的定义中做到这一点也是一个宣言。

4

4 回答 4

3

我不会那样做的。这是我要做的改变:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      >
    Foo
      ( Iterator first
      , Iterator last
      , typename enable_if<is_iterator<Iterator> >::type* = 0
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  >
Foo<T>::Foo(U f, U l, typename enable_if< is_iterator<U> >::type*)
{ ... }

这直接来自enable_if.

于 2011-02-27T20:30:38.063 回答
2

这是你想要完成的吗?[我没有is_iterator类型特征,因此我使用 C++0x 类型特征和实用程序库重新设计了您的示例。它应该与 TR1 和 Boost 库以相同的方式工作。]

#include <utility>
#include <type_traits>

template <typename T>
struct S
{
    // Constructor (1)
    S(T, T); 

    // Constructor (2)
    template <typename U>
    S(U, U, typename std::enable_if<std::is_integral<U>::value>::type* = 0);
};

template <typename T>
S<T>::S(T, T)
{ }

template <typename T>
template <typename U>
S<T>::S(U, U, typename std::enable_if<std::is_integral<U>::value>::type*)
{ }

int main()
{
    S<double> a(1.0, 2.0); // uses (1)
    S<double> b(1, 2);     // uses (2)
}
于 2011-02-27T20:30:04.807 回答
1

您可以做的最简单的事情是:

template<class Iterator>
Foo
  ( Iterator first
  , typename enable_if<is_iterator<Iterator>, Iterator>::type last
  );
于 2011-02-27T20:34:44.193 回答
1
template <class T>
struct Foo
  {
    Foo(T a, T b);

    template <class Iterator
      ,       class = typename std::enable_if
                       <is_iterator<Iterator>::value>
                       ::type
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{  }

template <class T>
template
  < class U
  , class >
Foo<T>::Foo(U f, U l)
{  }
于 2011-02-27T20:36:43.663 回答