1

Consider these two functions:

template <class Type, 
          class = typename std::enable_if</*HAS OPERATOR <<*/>::type>
void f(std::ostream& stream, const Type& value);

template <class Type, 
          class... DummyTypes,
          class = typename std::enable_if<sizeof...(DummyTypes) == 0>::type>
void f(std::ostream& stream, const Type& value, DummyTypes...);

As the non-variadic overload has the priority over the variadic overload, I want to check whether the type has the operator<< with an std::ostream using std::enable_if in the first version.

So what should I write instead of /*HAS OPERATOR <<*/ ?

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • possible duplicate of [Is it possible to write a C++ template to check for a function's existence?](http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence) – Xeo Oct 06 '13 at 18:45
  • Specifically, check my answer in the dupe. – Xeo Oct 06 '13 at 18:45

3 Answers3

7

The following should work

template <class Type, 
          class = decltype(std::declval<std::ostream&>() << std::declval<Type>())>
void f(std::ostream& stream, const Type& value)
{
    stream << value;
}

(note you don't need to use std::enable_if in this case)

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
6

Using trailing return type (1), you can actually have a foretaste of concepts:

template <typename Type>
auto f(std::ostream& out, Type const& t) -> decltype(out << t, void()) {
    // ...
}

Because of SFINAE, this overload can only be selected if the type of out << t can be resolved, and this implies that an overload of << exists that accepts both parameters.

The one pitfall is that this does not work if you need the contrary, that is enabling a function if this overload does not exists. In this case an enable_if strategy (and the symmetric disable_if) is necessary, as far as I know.

(1) thanks to Simple for helping out with the syntax

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
2

It is easiest to check when you have the arguments around, i.e., I would rather try to use something like this:

template <typename Type>
auto f(std::ostream& out, Type const& value)
    -> typename std::enable_if<sizeof(out << value) != 0>::type {
    ...
}

A similar effect could be obtained using std::declval() but off-hand I'm not sure about creating references.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380