7

I want to overload operator<< for arbitrary arrays, such that the code cout << my_arr would work. First I tried to overload the second parameter of operator<< on const T (&arr)[N], where T and N are template parameters. But testing the code revealed a side effect: const char[] also matches the type specification, and the new overload conflicts with the one defined in the stream class. Example code:

#include <cstddef>
#include <iostream>

template<typename T, std::size_t N>
std::ostream& operator<<(std::ostream& os, const T (&arr)[N])
{
    /* do stuff */
    return os;
}

int main()
{
    std::cout << "noooo\n"; /* Fails: ambiguous overload */
}

Can such an array printing operator still be implemented?

5
  • I don't think N will transfer well in a lot of cases. void f(int arr[], size_t N){ cout<<arr; } Commented Feb 23, 2012 at 21:31
  • if you want an external library why not just use boost.org/doc/libs/1_48_0/doc/html/boost_lexical_cast.html Commented Feb 23, 2012 at 21:33
  • 1
    @Captain: arr actually has the type int* in that case, so it wouldn't match that overload. Commented Feb 23, 2012 at 21:49
  • @GeorgFritzsche You are correct. A simple test revealed "error: no matching function for call to ‘operator<<(std::ostream&, int*&)’" Thanks! Commented Feb 23, 2012 at 21:59
  • 1
    possible duplicate of overloading operator<< for arrays Commented Feb 23, 2012 at 23:43

1 Answer 1

5

Sure:

template<typename T, std::size_t N>
typename std::enable_if<!std::is_same<T, char>::value, std::ostream&>::type
operator<<(std::ostream& os, const T (&arr)[N])
{
    // ...
}

This will disable your overload when T is char using SFINAE.

For C++03, Boost has enable_if and is_same. Alternatively just roll your own:

template<class T, class U> struct is_same { 
    enum { value = false }; 
};
template<class T> struct is_same<T, T> { 
    enum { value = true }; 
};

template<bool, class T> struct enable_if {};
template<class T> struct enable_if<true, T> { 
    typedef T type; 
};
Sign up to request clarification or add additional context in comments.

2 Comments

@Mr.Anubis: Use boost::enable_if and boost::is_same instead. If you don't want Boost, implement them yourself, these two are trivial.
@GeorgFritzsche: You're right. But should it be? I guess that const T(&)[] can bind to a non-const array also, so yeah, it's fine as written. It's deeper levels of const that can't be added implicitly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.