Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define template function only for classes derived from a single base

Tags:

c++

templates

I have a base class Base, that a lot of other classes will be derived from. I would like to define:

template<typename Derived>
ostream &operator<< (ostream &o, Derived &derived) {
}

But only for classes derived from Base. I need all previously defined operator<< to be used for other types. How to do that? Is that possible?

I cannot create ostream &operator<< (ostream &o, Base &base), because I need the exact type to be used in some type traits. Is there any way to "push" the derived type while passing the value as a base type?

like image 605
Juraj Blaho Avatar asked Feb 24 '11 18:02

Juraj Blaho


2 Answers

http://www.boost.org/doc/libs/1_46_0/libs/utility/enable_if.html

http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html

template<typename Derived>
typename enable_if<is_base_of<Base, Derived>, ostream&>::type
operator<< (ostream &o, Derived &derived) 
{

}
like image 92
Anycorn Avatar answered Sep 28 '22 01:09

Anycorn


You can use type traits and SFINAE to let only classes derived from Base into your function:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>

struct Base {};

template<typename Derived>
typename boost::enable_if<boost::is_base_and_derived<Base, Derived>, std::ostream&>::type
operator<<(std::ostream& o, Derived& derived);

struct A : Base {};
struct B : Base {};
struct C {};

int main()
{
    A a;
    B b;
    C c;
    std::cout << a << '\n'; // compiles
    std::cout << b << '\n'; // compiles
    std::cout << c << '\n'; // error: no match for 'operator<<' in 'std::cout << c'
}
like image 43
Maxim Egorushkin Avatar answered Sep 28 '22 01:09

Maxim Egorushkin