Here's a fully reproducible PoC of the problem, posted on Compiler Explorer: https://godbolt.org/z/x78Ksro88.
I'm encountering the following problem: the compiler is reporting an error because it cannot convert argument 2 (in the search_in
function) from type T
to the actual type in a situation where T
represents a template type.
template <typename T>
void analyze(vegtable& type, const std::vector<std::uint8_t>& dee, T& pee, int ole, std::uint16_t cee)
{
switch (type)
{
case type::banana:
beta::search_in(dee, pee, ole, cee);
break;
case type::orange:
gemma::search_in(dee, pee, ole, cee);
break;
case type::lemon:
zeta::search_in(dee, pee, ole, cee);
break;
default:
break;
}
}
vegetable
is a typed class enum of type std::uint8_t
.
I call the analyze function as follows (sample
is of type potato
):
analyze<potato>(organic, data, sample, 12);
where some of the types are defined as follows, for example:
vegetable organic;
organic = vegetable::banana;
struct potato
{
int x;
int y;
int z;
};
potato sample;
If I delete the function calls for the switch cases type::orange:
and type::lemon:
, the code compiles and works as expected, but if I leave the analyze function as shown, the compiler throws the error stated in the prologue of this question. This is a weird behaviour!
Note: there are other types too that I pass with the T
argument other than the potato
type, as shown in the PoC.
I can guarantee at the time of calling the analyze
function, that the T
type passed to each of the cases through the search_in
function call is of the correct type. It seems that the compiler is not able to figure it out!
You expect that since you passed to correct enum value that only the case that matters is called, and you are correct in that, the issue is that if the enum value does not match the correct case, then you are calling the wrong function. Since none of this checking is done at compile time the compiler is forced to check the entire function to make sure all paths compile and in your case they do not.
Since all of you search_in
functions are the same except for pee
parameter there is no reason to even use a switch case statement and instead you can just rely on overload resolution to call the correct function for you like:
template <typename T>
void analyze(vegetable& place, const std::vector<std::uint8_t>& dee, T& pee, int ole, std::uint16_t cee)
{
using beta::search_in;
using gemma::search_in;
using zeta::search_in;
search_in(dee, pee, ole, cee);
}
You can see this working with your example code in this live example.