Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::is_base_of for templated vector function parameter

I want to provide two different implementations of an operator>> depending on whether the given type is a subclass of a special type:

class A {};

class B : public A{};
class C {};

template<typename T>
std::istream& operator>>(std::istream& is,
    std::vector<typename std::enable_if<std::is_base_of<A, T>::value>::type>& vec)
{
    std::cout << "Special case called" << std::endl;
    return is;
}

template<typename T>
std::istream& operator>>(std::istream& is,
    std::vector<T>& vec)
{
    std::cout << "General case called" << std::endl;
    return is;
}


void main(int argc, char **argv)
{
    std::vector<A> a;
    std::vector<B> b;
    std::vector<C> c;
    std::stringstream ss("A string");
    ss >> a;
    ss >> b;
    ss >> c;
}

Which prints

General case called
General case called
General case called

Changing the second operator definition to

template<typename T>
std::istream& operator>>(std::istream& is,
    std::vector<typename std::enable_if<!std::is_base_of<A, T>::value>::type>& vec)
{
    std::cout << "General case called" << std::endl;
    return is;
}

Does not compile because of

error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::stringstream'

So I am probably using std::enable_if wrong. But what is correct? Are there problems with the templated std::vector here?

like image 298
PhilLab Avatar asked Mar 23 '26 15:03

PhilLab


1 Answers

I don't think the std::enable_if is in the most desired position here, I would put it in the return type to enable SFINAE:

template<typename T>
typename std::enable_if<std::is_base_of<A, T>::value,std::istream>::type& 
operator>>(std::istream& is,std::vector<T>& vec)
{
    std::cout << "Special case called" << std::endl;
    return is;
}

template<typename T>
typename std::enable_if<!std::is_base_of<A, T>::value,std::istream>::type& 
operator>>(std::istream& is,std::vector<T>& vec)
{
    std::cout << "General case called" << std::endl;
    return is;
}

live demo

like image 112
Biggy Smith Avatar answered Mar 25 '26 05:03

Biggy Smith