galinette
galinette

Reputation: 9292

checking iterator type in a container template class

I am writing a container class, and want to provide a constructor taking iterators as parameter, but only if the underlying iterated type matches the container type.

So I wrote:

template<typename T>
class Buffer
{
public:
    template <typename InputIter>
    typename std::enable_if<std::is_same<typename std::iterator_traits<InputIter>::value_type, typename T>>::type
    Buffer(InputIter first, InputIter last)
    {
    }
};

But I have compilation errors saying the template argument 1 and 2 are invalid

What is wrong?

Code with compiler here : https://onlinegdb.com/SyIqN_mBG

Upvotes: 4

Views: 595

Answers (2)

Jarod42
Jarod42

Reputation: 217573

SFINAE has 3 usable places:

  • as return type
  • as parameter type
  • as template type

For constructor, you cannot use return type.

I suggest default template parameter:

template<typename T>
class Buffer
{
public:
    template <typename InputIter,
              typename std::enable_if<
                           std::is_same<typename std::iterator_traits<InputIter>::value_type,
                                        T>::value,
                                      bool>::type = false>
    Buffer(InputIter first, InputIter last)
    {
    }
};

Upvotes: 5

Almost there. What you need to remember, as you were told in comments, is that constructors don't have return types. The usual trick of SFINAE on the return type won't work on them.

But they can have additional template parameters, ones that are always defaulted anyway, but the mere existence of can be used for SFINAE. So let's use that very test you provided (after adding a missing ::value) to add a non-type template parameter to the c'tor:

template<typename T>
class Buffer
{
public:
    template <typename InputIter, 
      typename std::enable_if<std::is_same<typename std::iterator_traits<InputIter>::value_type, T>::value, int>::type = 0>
    Buffer(InputIter first, InputIter last)
    {
    }
};

So if the iterators are proper, we have an additional int = 0, and if they aren't, SFINAE! The c'tor is removed from the set of overloads.

Upvotes: 8

Related Questions