Search code examples
c++templatesboostconstructorenable-if

type signature of an enable_if'ed templated template constructor?


I usually declare my classes and templates, and then define their methods after (in the same header file, of course). I just find it easier to read that way. Well, I've come across a case where I can't figure out a working type signature to use in an out-of-class definition. Here's a simplified example of what I'm doing, that illustrates the problem:

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)
{ ... }

I have tried a number of things in the WHAT_GOES_HERE slot to try to get a matching signature, and I keep failing. I need the enable_if to distinguish the case where one passes in two objects of type T, and when one passes in a pair of Iterators. The code works fine if the templated constructor is defined inside the main template, which is how the code currently does it, but I'd much rather move the definition outside the declaration.

EDIT: I should mention that I can't just re-use enable_if<...> in the definition, because enable_if<...> assigns a default value for its type, which you cannot do in a definition that isn't also a declaration.


Solution

  • I wouldn't do it that way. Here's the changes I would make:

    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*)
    { ... }
    

    This is straight out of the documentation for enable_if.