What you are trying to achieve cannot be done as it is. The language does not allow you to have a function that, based on some runtime data, changes its return type. Depending on the problem you are trying to solve, there may be different alternatives, such as defining a generic type that can be used to represent either bar1 or bar2 , or to reorganize the code, so you don't need to return everything.
That is, if something cannot be determined at compile time ... if it can be determined that you can use metaprogramming to determine the type of return you need.
You should provide a more detailed description of the real problem, after which you can get clearer ideas as to which direction to go.
You can try something in the lines:
template <bool value> struct Bool {}; template <typename T, typename U> T f_impl(T t, U u, Bool<true>) { return t; } template <typename T, typename U> T f_impl(T t, U u, Bool<false>) { return u; } template <int A, int B, int C, int D, int E, int F> auto f(MyClass<A,B,C> a, MyClass<D,E,F> b) -> f_impl(a, b, Bool<!(A < D || (A == D && B < E) || (A == D && B == E && C < F))>()) { return f_impl(a, b, Bool<!(A < D || (A == D && B < E) || (A == D && B == E && C < F))>()); }