gpt4 book ai didi

c++ - 如何让 C++ ADL 查看模板的所有实例?

转载 作者:IT老高 更新时间:2023-10-28 21:43:25 26 4
gpt4 key购买 nike

我正在关注 How to implement a constant-expression counter in C++教程 我正在尝试修复 C++14 Reflections Without Macros, Markup nor External Tooling..谈话限制。

本教程的基本思想是这样的:

template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};

template<int N>
struct writer {
friend constexpr int adl_flag (flag<N>) { return N; }
static constexpr int value = N;
};

template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<C + N>::value) { return R; }

int main () {
constexpr int a = next ();
constexpr int b = next ();
constexpr int c = next ();

// YES! it works!!!
static_assert (a == 1 && b == a+1 && c == b+1, "try again");
}

注意:如果你现在不感兴趣,现在是停止阅读的好时机:-)

演讲还解释了如何使用聚合初始化和隐式转换运算符为 POD 类型提取字段数量和字段类型,但主要限制是仅支持原始类型。

我提供了上述背景来证明我的动机!

当我结合这两种方法时,我得出了这个结论:

template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};

template<typename T, int N>
struct writer {
friend constexpr int adl_flag (flag<N>) {
return N;
}
friend constexpr T field_type(flag<N>) { return T{}; }
static constexpr int value = N;
};

field_type(flag<N>)会给我 N 的类型字段。请注意,它是一个友元函数,对于 N POD 的第一个字段准确输入一个 field_type(flag<N>)将由编译器定义。

g++给我no matching function for call to 'field_type(flag<1>)对于 decltype(field_type(flag<1>)) .

我需要以某种方式强制 ADL搜索 writer<T,N> 的所有实例.我该怎么做?

更新

正如@T.C.提到的,ADL 只查看相关的类,writer不是一个。 (这就是 adl_flagflag 中声明的原因 - 以便 ADL 可以找到它。)

整个问题是如何制作 writer不知道 T 的关联类值使得 ADL能找到吗?

最佳答案

在标志模板中添加field_type声明,返回类型为auto(仅在C++14之后可用)

仅适用于 gcc 4.9:

#include <type_traits>

template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
friend constexpr auto field_type(flag<N>);
};

template<typename T, int N>
struct writer {
friend constexpr int adl_flag (flag<N>) { return N; }
friend constexpr auto field_type(flag<N>) { return (T&&)(*(T*)0); } // remove default constructable restriction
static constexpr int value = N;
};

template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<typename T, int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<T, C + N>::value) { return R; }

int main () {
constexpr int a = next<int> ();
constexpr int b = next<double> ();
constexpr int c = next<long> ();

// YES! it works!!!
static_assert (a == 1 && b == a+1 && c == b+1, "try again");
static_assert(std::is_same<decltype(field_type(flag<1>{})), int>{}, "first is int");
static_assert(std::is_same<decltype(field_type(flag<2>{})), double>{}, "second is double");
static_assert(std::is_same<decltype(field_type(flag<3>{})), long>{}, "third is long");

}

使用 decltype 的 auto 函数而不是 noexcept,在 gcc 5.2、clang 3.5.1 - 3.7.1 之后工作:

#include <type_traits>

template <int N>
struct flag {
constexpr friend auto adl_flag(flag<N>);
friend auto field_type(flag<N>);
};

template<typename T, int N>
struct writer {
friend constexpr auto adl_flag(flag<N>) { return 0; }
friend auto field_type(flag<N>) { return (T&&)(*(T*)0); }
static constexpr int value = N;
};

template<int N, class = decltype(adl_flag(flag<N>{}))>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<typename T, int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<T, C + N>::value) { return R; }

int main () {
constexpr int a = next<int> ();
constexpr int b = next<double> ();
constexpr int c = next<long> ();

// YES! it works!!!
static_assert (a == 1 && b == a+1 && c == b+1, "try again");
static_assert(std::is_same<decltype(field_type(flag<1>{})), int>{}, "first is int");
static_assert(std::is_same<decltype(field_type(flag<2>{})), double>{}, "second is double");
static_assert(std::is_same<decltype(field_type(flag<3>{})), long>{}, "third is long");

}

关于c++ - 如何让 C++ ADL 查看模板的所有实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40008554/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com