如果我有一个元组成员变量,其中元组中的类型是类模板的参数包,我可以使用静态成员函数将函数应用于元组中的每个对象,如下所示:
template<size_t I = 0, typename F, typename... Tp>
static void apply_to_foos(std::tuple<Tp...>& t, F func) {
auto& foo = std::get<I>(t);
func(foo);
if constexpr (I + 1 != sizeof...(Tp))
apply_to_foos<I + 1>(t, func);
}
例如,如果 foos_
是元组成员变量,我可以通过 foos 实现成员函数:
void frobnicate() {
apply_to_foos( foos_, [](auto& f){f.frob();} );
}
等等。但是,如果 frobnicate
一直是 const 我遇到了 foos_
的问题现在将是 const,并且 apply_to_foos
想要一个非常量元组。例如,这将不起作用(如果 foos 是某种容器)
size_t size() const {
size_t sz = 0;
apply_to_foos( foos_, [&sz](auto& f){ sz += f.size();} );
return sz;
}
我可以实现 apply_to_foos
的重载这需要 const std::tuple<Tp...>&
, const_cast 到一个非常量元组并调用原始重载,但是,好吧,那么我只是抛弃 const 性。
令人烦恼的是 apply_to_foos
的唯一部分关心常量的是签名。只要遵守常量性,其他所有内容都可以使用 const 值,例如lambda 需要引用 const 值等。如果我可以从 const 元组转换为 const 元组,那么我可以像这样实现 const 重载:
template<size_t I = 0, typename F, typename... Tp>
static void apply_to_foos(const std::tuple<Tp...>& t, F func) {
auto& tup_of_consts = const_tuple_to_tuple_of_consts(t);
apply_to_foos(tup_of_consts, func);
}
和size()
成员函数会自然地工作......我觉得必须有一种更简单的方法来处理这个问题?
最佳答案
您无法转换 const std::tuple<T1, T2>
至std::tuple<const T1, const T2>
无需复制所含元素。
您有两种选择:
1。推导出 t
的类型并完全回避问题:
template<size_t I = 0, typename F, typename T>
static void apply_to_foos(T& t, F func) {
auto& foo = std::get<I>(t);
func(foo);
if constexpr (I + 1 != std::tuple_size<T>::value)
apply_to_foos<I + 1>(t, func);
}
类型为t
推断,这两种情况都会起作用。如果通过了const
元组然后 T
将被推导为 const std::tuple<...>
制作 t
的类型const std::tuple<...>&
如果通过了非 const
元组然后 T
将被推导为std::tuple<...>
和 t
的类型将是std::tuple<...>&
。唯一需要的其他更改是使用 std::tuple_size<T>::value
代替sizeof...(Tp)
。请注意,这也允许 apply_to_foos
与其他类型一起使用,例如 std::array
和std::pair
.
您可能还想应用完美转发以允许 apply_to_foos
使用右值并保留元组元素的值类别。例如:
template<size_t I = 0, typename F, typename T>
static void apply_to_foos(T&& t, F func) {
func(std::get<I>(std::forward<T>(t)));
if constexpr (I + 1 != std::tuple_size<std::remove_reference_t<T>>::value)
apply_to_foos<I + 1>(std::forward<T>(t), func);
}
2。创建一个包含对原始元组内容的引用的新元组
创建 apply_to_foos
的第二个重载接受对 const
的引用元组并创建一个临时元组 const
对原始元组元素的引用:
template<typename F, typename... Tp>
static void apply_to_foos(const std::tuple<Tp...>& t, F func) {
std::tuple<std::add_const_t<Tp>&...> tuple_of_const = t;
apply_to_foos(tuple_of_const, func);
}
这可以正常工作,但它在值类别保存方面存在问题。元组右值的元素将作为 const
传递给回调函数。例如,左值不能轻易移动。
关于c++ - const 元组到 const 元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66002324/