тип подписи шаблонного шаблона конструктора enable_if? - PullRequest
6 голосов
/ 27 февраля 2011

Я обычно объявляю свои классы и шаблоны, а затем определяю их методы (в том же заголовочном файле, конечно).Мне просто легче читать таким образом.Ну, я сталкивался со случаем, когда я не могу определить сигнатуру рабочего типа для использования в определении вне класса.Вот упрощенный пример того, что я делаю, который иллюстрирует проблему:

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 ]

3 голосов
/ 27 февраля 2011

Я бы так не поступил.Вот изменения, которые я бы сделал:

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.

2 голосов
/ 27 февраля 2011

Это то, что вы пытаетесь достичь? [У меня нет черты типа 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)
}
1 голос
/ 27 февраля 2011
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)
{  }
1 голос
/ 27 февраля 2011

Самое простое, что вы можете сделать:

template<class Iterator>
Foo
  ( Iterator first
  , typename enable_if<is_iterator<Iterator>, Iterator>::type last
  );
...