【问题标题】:Alternative to template ADL for GCC <= 10GCC <= 10 的模板 ADL 的替代方案
【发布时间】:2021-11-18 13:02:55
【问题描述】:

考虑以下有效的 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>());
}

这里,get&lt;N&gt; 能够通过 ADL 解析,这要归功于 C++20 添加 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0846r0.html)

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

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

【问题讨论】:

    标签: c++ c++20 argument-dependent-lookup


    【解决方案1】:

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

    当模板被实例化时,将通过 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;
    

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

    【讨论】:

    • template &lt;std::size_t&gt; void get() = delete; 就足够了,不需要Dummy,只需要一个名为get 的模板函数。
    • 那就更好了。
    猜你喜欢
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多