0

In the following code, A is a template class, depending on a non-type bool type parameter. A friend operator<< is defined for both A<true> and A<false>. The operator<< additionally depends on another bool template parameter.

#include <ostream> #include <iostream> #include <type_traits> template <bool type> class A; template <> class A<true> { int m_x; public: A(int x) : m_x{x} { } template <bool d, bool type> friend std::ostream& operator<<(std::ostream& os, const A<type>& a); }; template <> class A<false> { int m_y; public: A(int y) : m_y{y} { } template <bool d, bool type> friend std::ostream& operator<<(std::ostream& os, const A<type>& a); }; template <bool d, bool type> std::ostream& operator<<(std::ostream& os, const A<type>& a) { if constexpr (type) { os << "m_x = " << a.m_x << std::endl; if constexpr (d) { os << "2m_x = " << a.m_x << std::endl; } } else { os << "m_y = " << a.m_y << std::endl; if constexpr (d) { os << "2m_y = " << a.m_y << std::endl; } } return os; } int main() { A<true> atrue{2}; A<false> afalse{3}; operator<< <true>(std::cout, atrue); operator<< <false>(std::cout, atrue); operator<< <true>(std::cout, afalse); operator<< <false>(std::cout, afalse); return 0; } 

See it live on Coliru.

Now, I would like to give a default value of the template parameter d of operator<<, say d=false such that this statement

std::cout << atrue; 

is equivalent to

operator<< <false>(std::cout, atrue); 

because bool d takes a default value d=false and bool type is deduced from the second argument of operator<<.

Is there a syntax to allow for that?

If I insert the default parameter in the friend declaration

template <bool d = false, bool type> friend std::ostream& operator<<(std::ostream& os, const A<type>& a); 

I get a compile error:

main.cpp:14:71: error: default template arguments may not be used in template friend declarations

If I insert the default parameter in the code of operator<<

template <bool d = false, bool type> std::ostream& operator<<(std::ostream& os, const A<type>& a) { ... 

again it does not compile giving error

main.cpp:27:15: error: redeclaration of friend 'template std::ostream& operator<<(std::ostream&, const A&)' may not have default template arguments

27 | std::ostream& operator<<(std::ostream& os, const A& a)

main.cpp:14:26: note: 'template std::ostream& operator<<(std::ostream&, const A&)' previously declared here

14 | friend std::ostream& operator<<(std::ostream& os, const A& a);

1
  • How about use other name than operator << as print as you cannot use it "normally"? Commented Feb 3, 2020 at 14:01

1 Answer 1

1

OK, actually the solution was relatively easy. It is enough to add a declaration of the template operator<< before the class specializations:

template <bool type> class A; template <bool d = false, bool type> std::ostream& operator<<(std::ostream& os, const A<type>& a); .... 

In this way the friend declaration inside A<type> does not declare operator<< in first place, but only declares that it is a friend. A working example can be checked here.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.