编译以下(精简)代码时:
#include <tuple>
#include <stdlib.h>
template<size_t N> struct tying;
template<> struct tying<1> {static auto function(auto& o) -> decltype(auto) {auto& [p1] = o;return std::tie(p1);}};
template<> struct tying<2> {static auto function(auto& o) -> decltype(auto) {auto& [p1,p2] = o;return std::tie(p1,p2);}};
template<typename T, size_t N> concept bool n_components =
requires(T& object) {
{ tying<N>::function(object) };
};
typedef struct
{
int a;
float b;
} test_t;
int main(int argc, char* argv[])
{
constexpr size_t n = 1;
constexpr bool t = n_components<test_t, n>;
printf("n_components<test_t, %d>: %s\n", n, t ? "yes" : "nope");
return 0;
}
使用 gcc 特定选项 -std=c++1z -fconcepts
gcc(版本 7.3.0,以及 godbolt 的 x86-64 gcc-trunk 也)失败并出现错误:
error: only 1 name provided for structured binding
note: while 'test_t' decomposes into 2 elements
我对此感到非常惊讶,因为错误在 requires-expression
中“引发” ,据我了解,这应该导致 n_components
约束条件被评估为 false,因为不满足要求。
注意:替换constexpr size_t n = 1;
使用其他值“修复”错误,所以我假设 n_components
约束不是罪魁祸首:
- 替换为
n = 2
n_components
约束按预期评估为“真”。 - 替换为
n = 3
n_components
约束按预期计算为“false”——由于引用了未专门化的tying<3>
结构。
似乎还没有其他支持 c++ 概念和结构化绑定(bind)的编译器可供比较。
附言。我在玩“穷人的反射(reflection)”又名 magic_get
并希望取代不可靠的 is_braces_constructible
具有更强大的特性......
最佳答案
这是自 5.0 以来 clang 的部分解决方案。
它是从最近的 reddit 帖子中提炼出来的
Find the number of structured bindings for any struct
该方法是非标准的,使用 gnu 扩展语句表达式 来有效地对结构化绑定(bind)声明进行 SFINAE。它也是不可移植的,因为 gcc 无法解析 lambda 尾随返回类型中语句表达式中的结构化绑定(bind)。
template <typename... Ts> struct overloads : Ts... { using Ts::operator()...; };
template <typename... Ts> overloads(Ts...) -> overloads<Ts...>;
template <typename T>
auto num_bindings_impl() noexcept {
return overloads{
[](auto&& u, int) -> decltype(({auto&& [x0] = u; char{};}))(*)[1] {return {};},
[](auto&& u, int) -> decltype(({auto&& [x0,x1] = u; char{};}))(*)[2] {return {};},
[](auto&& u, int) -> decltype(({auto&& [x0,x1,x2] = u; char{};}))(*)[3] {return {};},
[](auto&& u, int) -> decltype(({auto&& [x0,x1,x2,x3] = u; char{};}))(*)[4] {return {};},
[](auto&& u, unsigned) -> void {}
}(declval<T>(), int{});
};
此实现仅用于未评估的上下文并扩展
对于任意数量的绑定(bind),直到编译器实现限制。
然后,您可以定义达到该限制的特征:
template <typename T>
inline constexpr bool has_bindings = [] {
if constexpr ( ! is_empty_v<T> )
return ! is_void_v< decltype(num_bindings_impl<T>()) >;
else return false;
}();
template <typename T>
inline constexpr unsigned num_members = [] {
if constexpr ( ! is_empty_v<T> )
return sizeof *num_bindings_impl<T>();
else return 0;
}();
关于c++ - 如何编写结构化绑定(bind)的概念?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49340829/