I have a function
template <typename T1, typename T2>
/*return type*/ foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
if (something)
return bar1;
else
return bar2;
}
The problem is, that I don't know what will this function return: it can be either MyClass<T1>
or MyClass<T2>
.
How can I get it to work?
T1 and T2 are structs of 3 ints, known at compile time. The return type depends on the smaller of those 2: for example for T1 = <5, 1, 1>
T2 = <4, 4, 7>
return type should be MyClass<T2>
.
Example usage:
MyClass<5, 2, 8> m1;
MyClass<4, 2, 1> m2;
cout << foo(m1, m2); //should print m2 (I have a method used for that)
What you are trying to achieve there cannot be done as 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 that you are trying to solve, there might be different alternatives, like determining a common type that can be used to represent either bar1
or bar2
or reorganizing the code so that you don't need to return at all.
That is if something
cannot be determined at compile time... if it can be determined you can have some metaprogramming in place to determine the return type to be the one you need.
You should provide a higher level description of the real problem, after which you might get better ideas as of what direction to take.
You can try something in the lines of:
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))>());
}
You can define two functions from which only one will be instantiated for given types:
template <typename T1, typename T2>
struct ChooseFirst;
template <int A1, int B1, int C1, int A2, int B2, int C2>
struct ChooseFirst<MyClass<A1, B1, C1>, MyClass<A2, B2, C2>> {
// this requires constexpr make_tuple (C++14)
static const bool value = std::make_tuple(A1, B1, C1) < std::make_tuple(A2, B2, C2);
// if in your implementation make_tuple is not constexpr, you can write the comparison manually:
// static const bool value = A1 < A2 || (A1 == A2 && (B1 < B2 || (B1 == B2 && C1 < C2)));
};
template <typename T1, typename T2>
typename std::enable_if<ChooseFirst<T1, T2>::value, T1&>::type foo(T1& bar1, T2&) {
return bar1;
}
template <typename T1, typename T2>
typename std::enable_if<!ChooseFirst<T1, T2>::value, T2&>::type foo(T1&, T2& bar2) {
return bar2;
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With