Reputation: 4386
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.
Upvotes: 5
Views: 171
Reputation: 48447
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.
Upvotes: 3