1

I managed to overload insertion operator for std::ostream based on rank of object. I would like to extend below example.

When A_new.h is included, it includes A.h... in this case I am checking rank of object and I am calling f_alterantive or f_old. Works as expected :)

The problem appears when A.h is included directly, then there only one instance of f() - f_old.

If there is only one instance of f() included directly through A.h, then it should be default for all objects... (not only for rank > 1, but also for all rest) and below condition has no sense.

typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 > 

I know that I need to specify condition which checks if another f() exists: something like:

//goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 > 

I found similar question, but I am still not sure how to do it with std::enable_if

#include <iostream> #include <type_traits> #include <sstream> class Foo { }; //--- alternative header A_new.h //#include A.h template< class T, typename std::enable_if<(std::rank<T>::value == 1), int>::type = 0 > void f(std::ostream& os, const T& value) //f_alternative { os << "alternative function\n"; os << "rank == 1" << std::endl; } //---- //---- old header A.h template < class T, typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 > //goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 > void f(std::ostream& os, const T& value) //f_old { os << "old function\n"; os << "rank > 1" << std::endl; } template <class T> std::ostream& operator<<(std::ostream& os, const T& foo) { f<T>(os, foo); return os; } //----- int main() { Foo foo1[5]; Foo foo2[5][5]; std::cout << foo1; std::cout << foo2; return 0; } 

https://coliru.stacked-crooked.com/a/7f7ef7bda1805a36

Could you tell me how can I specify std::enable_if to work also when f() is not overloaded and when it should run for all cases?

1 Answer 1

2

A possible f_alternative_exist is the following

template <typename T> std::false_type f_alternative_exist_f (std::ostream &, T const &, long); template <typename T> auto f_alternative_exist_f (std::ostream & os, T const & t, int) -> decltype( f(os, t), std::true_type{} ); template <typename T> using f_alternative_exist = decltype(f_alternative_exist_f(std::declval<std::ostream &>(), std::declval<T>(), 0)); template <typename T> static constexpr bool f_alternative_exist_v = f_alternative_exist<T>::value; 

The old version become

template <typename T, std::enable_if_t<(std::rank<T>::value > 1) || (false == f_alternative_exist_v<T>), int> = 0 > void f (std::ostream & os, T const &) { os << "old function\n"; os << "rank > 1" << std::endl; } 

The following is a full compiling C++14 example

#include <iostream> #include <type_traits> #include <sstream> class Foo { }; template <typename T> std::false_type f_alternative_exist_f (std::ostream &, T const &, long); template <typename T> auto f_alternative_exist_f (std::ostream & os, T const & t, int) -> decltype( f(os, t), std::true_type{} ); template <typename T> using f_alternative_exist = decltype(f_alternative_exist_f(std::declval<std::ostream &>(), std::declval<T>(), 0)); template <typename T> static constexpr bool f_alternative_exist_v = f_alternative_exist<T>::value; #if 0 // enable/disable template <typename T, std::enable_if_t<std::rank<T>::value == 1, int> = 0 > void f (std::ostream & os, T const &) { os << "alternative function\n"; os << "rank == 1" << std::endl; } #endif template <typename T, std::enable_if_t<(std::rank<T>::value > 1) || (false == f_alternative_exist_v<T>), int> = 0 > void f (std::ostream & os, T const &) { os << "old function\n"; os << "rank > 1" << std::endl; } template <typename T> std::ostream& operator<<(std::ostream& os, const T& foo) { f<T>(os, foo); return os; } int main () { Foo foo1[5]; Foo foo2[5][5]; std::cout << foo1; std::cout << foo2; } 
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.