std::apply可能未正确实现
std::apply may not be properly implemented
std::apply在少数stackerflow答案和n3658、n3915中被提及,通常被定义为:
template <typename F, typename Tuple, size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
return forward<F>(f)(get<I>(forward<Tuple>(t))...);
}
template <typename F, typename Tuple>
decltype(auto) apply(F&& f, Tuple&& t) {
using Indices = make_index_sequence<tuple_size<decay_t<Tuple>>::value>;
return apply_impl(forward<F>(f), forward<Tuple>(t), Indices{});
}
然而,引用实现std::apply函数未能在这样的上下文中编译(用clang 3.8和gcc 5.2测试):
std::apply ([] (int&) {} , std::make_tuple (42));
一种可能的解决方法是简单地删除std::forward<元组>来自apply_inpl,但保留通用参考:
template <typename F, typename Tuple, size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
return forward<F>(f)(get<I>(t)...);
}
这种变通方法有什么缺点吗?有更方便的解决方案吗?
更新:另一个不更改的可能解决方法std::apply(受此SO答案启发):
template <typename T> constexpr T& make_tmp (T&& t) noexcept { return t; }
...
std::apply ([] (int& i) {} , make_tmp (std::make_tuple (42)));
它是否正确,结果是否明确?
当您有一个包含临时对象(或对临时对象的引用)的临时元组时,要求可写引用的函数可以拒绝应用程序。该函数希望调用方注意它所写的内容,而你却坚决放弃了它
以下是编译的代码:
int main() {
int i = 42;
std::apply ([] (int&) {} , std::tie(i) );
}
make_tuple
创建一个副本的元组。然后,apply
在即将被丢弃的副本上调用传入的f
:这些副本被正确地视为右值。
如果有一个对象要通过std::apply
引用传递,请在元组中放置对它的引用,而不是它的副本。然后apply
中元组的右值不适用于引用内容。
对于std::get<N>(some_tuple)
返回右值,可以是:
(A) 第n个元素必须是副本,元组必须是右值
(B) 第n个元素必须是一个右值引用,元组必须是右值引用
通过存储左值引用,std::get
将永远不会返回右值引用。
根据具体情况,您可能需要调用std::tie
或std::forward_as_tuple
。std::make_tuple
用于在元组中创建副本,而不是存储对其他对象的引用。
当do想要放弃任何修改时,有一些方法可以允许您将右值作为左值传递,但这些通常是坏主意,应该在到处都是大警告标签的客户端代码中执行,而不是在库中隐式执行。
template<class T>
T& as_lvalue( T&& t ) { return t; }
是一个简单的问题。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在C++中,如何在类和函数(可能是模板化的)的头中编写完整的实现
- std::apply可能未正确实现