Consider the following valid C 20 code:
#include <utility>
namespace foo
{
template<typename... Args>
struct tuple : Args... { };
template<std::size_t N, typename... Args>
auto get(tuple<Args...>) { return 0; }
}
namespace bar
{
template<typename... Args>
struct tuple : Args... { };
template<std::size_t N, typename... Args>
auto get(tuple<Args...>) { return 0; }
}
template<class Tuple, std::size_t... N>
auto for_each(Tuple& args, std::index_sequence<N...>) {
(get<N>(args), ...);
}
int main()
{
struct test { };
foo::tuple<test> t;
for_each(t, std::make_index_sequence<1>());
}
Here, get<N>
is able to be resolved through ADL thanks to a C 20 addition (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0846r0.html)
My question is, what are the workarounds to this before C 20, which do not require the method for_each
to know about the foo
and bar
namespaces ?
I'd be happy with anything that works starting from GCC 8.
CodePudding user response:
You can add a dummy function and leave it without definition to make the compiler happy.
When the template is instatiated the right methods will be found through ADL.
#include <utility>
#include <tuple>
namespace foo
{
template<typename... Args>
struct tuple : Args... { };
template<std::size_t N, typename... Args>
auto get(tuple<Args...>) { return 0; }
}
namespace bar
{
template<typename... Args>
struct tuple : Args... { };
template<std::size_t N, typename... Args>
auto get(tuple<Args...>) { return 0; }
}
template <typename... T>
struct Dummy;
template <std::size_t N, typename... Args>
auto get(Dummy<Args...>);
template<class Tuple, std::size_t... N>
auto for_each(Tuple& args, std::index_sequence<N...>) {
(get<N>(args), ...);
}
int main()
{
struct test { };
foo::tuple<test> t;
for_each(t, std::make_index_sequence<1>());
}
Edit As suggested by @Jarod42 we can do
template <std::size_t N>
void get() = delete;
The compiler can't rule out that there is a valid specialization for that template later on, so the fact that it's deleted doesn't really matter here.