Consider the following code:
template <typename RetType, typename ResultFlagType>
struct Ret
{
RetType value;
ResultFlagType flag;
operator RetType() { return value; }
operator ResultFlagType() { return flag; }
};
template <typename T>
struct StructType
{
T a;
float b;
char c;
};
enum class ResultFlag
{
Success,
Failure,
};
template <typename T>
Ret<StructType<T>, ResultFlag> BuildStruct(T a, float b, char c)
{
return { { a, b, c }, ResultFlag::Success };
}
template <typename T>
Ret<StructType<T>, ResultFlag> ModifyStruct(StructType<T> s)
{
s.b += 3;
return { s, ResultFlag::Success };
}
int main()
{
auto ret = BuildStruct(3, 2.1, 'a');
if (ret == ResultFlag::Success)
{
ModifyStruct(ret);
}
}
In the current form, the compiler (GCC in this case) will fail the deduction/substitution step complaining that "Ret<StructType<int>, ResultFlag>' is not derived from 'StructType<T>"
Let's say we're not allowed to change main()
, ModifyStruct()
, or struct StructType
, is there a way to instruct the compiler to correctly deduce, or cast, ret
to the proper type automatically for us?
The only way I found so fa is to explicitly cast to the correct type when passing ret
to ModifyStruct
:
if (ret == ResultFlag::Success)
{
ModifyStruct((StructType<int>)ret); // Don't mind the C-Style cast.
}
Your problem is that template deduction happens before conversions are considered in overload resolution, so T
can't be deduced. This is one of the reasons that implicit conversion operators are not a great idea.
Not sure if this counts as "changing" ModifyStruct
, but you can add an overload
template <typename T>
Ret<StructType<T>, ResultFlag> ModifyStruct(Ret<StructType<T>, ResultFlag> ret)
{
return ModifyStruct(ret.value);
}