如何让非成员在<N>命名空间中为自定义类工作 [C++17]
How to get non-member get<N> to work for custom class in a namespace [C++17]
>C++17引入了结构化绑定声明:auto [a, b] = some_tuple;
.
这对于像 std::tuple 这样的东西来说是开箱即用的。也可以使其适用于自定义类型,您只需提供(除其他外)一个 get-function 模板,作为成员或在自定义类之外。
对于标准类,这是通过 std 命名空间中的非成员 get 完成的:auto a = std::get<0>(some_tuple);
有效,但不能auto a = some_tuple.get<0>();
。
但这里对我来说很奇怪:由于我们必须为 get 显式指定模板参数 N,因此 ADL 不起作用,例如,我们不能只写auto a = get<0>(some_tuple);
.但是,带有元组的结构化绑定声明也不应该起作用,因为它只是像get<N>(some_tuple)
或some_tuple.get<N>()
这样的调用的语法糖(模化一些&
)!事实上,当我只为命名空间内的自定义类提供非成员版本的 get 时,它不起作用!编辑:自定义类的结构化绑定也可以正常工作,请参阅接受答案中的代码片段以获取最小示例!
那么,标准的实现者如何在没有 get 作为成员的情况下使结构化绑定适用于元组,以及如何为我的自定义类实现相同的行为?
他们作弊。
但是您可以通过向全局命名空间添加模板 get 来模拟他们的作弊行为。
template<class T, std::enable_if_t<std::is_same<T,void>{}, bool>>
void get(int)=delete;
这应该激活"解析获取作为模板"。
您无需执行此操作即可使结构化绑定正常工作。 如前所述,编译器只是作弊:
namespace example {
struct silly {
int x;
};
template<std::size_t I>
int& get( silly& s ) { return s.x; }
}
namespace std {
template<>
struct tuple_size<::example::silly>:std::integral_constant<std::size_t, 1>{};
template<>
struct tuple_element<0, ::example::silly>{ using type=int; };
}
int main() {
example::silly s { 42 };
auto&& [x] = s;
std::cout << x;
}
相关文章:
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- C++自定义比较函数
- 如何比较自定义类的std::变体
- std::设置自定义比较器
- 如何正确实现和访问运算符的各种自定义枚举器
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 自定义先决条件对移动分配运算符有效吗
- 使用VS Code和CMake Tools运行自定义命令
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- std::ranges::elements_view,用于自定义类似元组的数据
- 跟随整数索引列表的自定义类迭代器
- 参数化自定义CMake工具链
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- '_HAS_CXX17'宏是否可用于自定义项目标头以启用C++17 语言集功能?
- C++17 和更新的 std::分配器是否适用于动态数量的自定义堆?
- MSVC++ 17 std::copy 期望自定义迭代器的"operator -"
- C++17 pimpl 习语上下文中的自定义迭代器
- 如何让非成员在<N>命名空间中为自定义类工作 [C++17]