I faced something I cannot understand nor find a way to work around properly. What I am trying to achieve looks relatively simple: I want to compare some data.
Best way to describe would be a line of code:
std::tuple<const char *, int, const char *, int> my_data =
std::make_tuple("hello", 13, "world", 37);
// Now I want to compare my_data againt some known value.
assert(Test::entry(my_data, "hello", 13, "world", 37));
I am using a tuple for the sake of the example. I my case, those data comes from a message object and are extracted using operator>>
. However, this is not related to the problem.
Here is a minimalist code to illustrate the problem.
#include <cstring>
using MyTuple = std::tuple<const char *, int, const char *, int>;
namespace Test
{
// called when we are done
bool extract(MyTuple source)
{
return true;
}
template<typename T,
typename ...Content>
bool extract(MyTuple source, T data, Content... content)
{
if (std::is_same<const char *, T>::value)
assert(0); // why ? :(
std::cout << "Generic: " << data << std::endl;
return extract(source, content...);
}
template<typename ...Content>
bool extract(MyTuple source, const char *str, Content... content)
{
std::cout << "Overloaded: " << str << std::endl;
return extract(source, content...);
}
template<typename ...Content>
bool entry(const std::tuple<const char *, int, const char *, int> &data,
Content... content)
{
return extract(data, content...);
}
};
I would normaly perform comparaison in the extract()
functions, but for keeping the example simple, I removed them.
What I want to achieve is proper dispatching. Based on the example it is my understanding that call order should be:
const char *
const char *
However, the output of this test program is:
Assertion failed
. The std::is_same
test trigger the assert
.What I discovered was that the const char *
overload will not be called after the generic overload has been call once.
I am missing something?
EDIT: Also not that if I define the const char *
overload before the generic function, this wont even compile.
Also note that if I define the
const char *
overload before the generic function, this wont even compile.
A declaration should suffice:
template <typename... Content>
bool extract(MyTuple source, const char *str, Content... content); // <- here
template <typename T, typename... Content>
bool extract(MyTuple source, T data, Content... content)
{
std::cout << "Generic: " << data << std::endl;
return extract(source, content...);
}
template <typename... Content>
bool extract(MyTuple source, const char *str, Content... content)
{
std::cout << "Overloaded: " << str << std::endl;
return extract(source, content...);
}
Why?
The overload taking const char*
is not visible during this particular name lookup without prior declaration. Some of the exceptions to this can be found in comments below.
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