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
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.
SFINAE has 3 usable places:
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)
{
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With