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
来了解 foo
和 bar
命名空间?
我对从 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;
编译器不能排除以后该模板有一个有效的特化,所以它被删除的事实在这里并不重要。
考虑以下有效的 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
来了解 foo
和 bar
命名空间?
我对从 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;
编译器不能排除以后该模板有一个有效的特化,所以它被删除的事实在这里并不重要。