GCC <= 10 模板 ADL 的替代方案

Alternative to template ADL for GCC <= 10

考虑以下有效的 C++20 代码:

#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>());
}

在这里,由于添加了 C++20 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0846r0.html)

get<N> 可以通过 ADL 解决

我的问题是,在 C++20 之前有什么解决方法,不需要方法 for_each 来了解 foobar 命名空间?

我对从 GCC 8 开始工作的任何东西都很满意。

您可以添加一个虚拟函数,不定义它以使编译器满意。

实例化模板后,将通过 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>());
}

编辑 正如@Jarod42 所建议的,我们可以做

template <std::size_t N>
void get() = delete;

编译器不能排除以后该模板有一个有效的特化,所以它被删除的事实在这里并不重要。