在帖åhere,hereå’ŒhereåŽé¢çš„C++14
ä¸è€ƒè™‘以下代ç :
// Include
#include <tuple>
#include <iostream>
#include <type_traits>
// Temporary function queue declaration
template <class... F>
class temporary_function_queue;
// Apply function queue declaration
template <class... F>
constexpr temporary_function_queue<F&&...> apply_function_queue(F&&... f);
// Temporary function queue definition
template <class... F>
class temporary_function_queue final
{
// Types
private:
using const_lvalue_reference = const temporary_function_queue&;
using rvalue_reference = temporary_function_queue&&;
using temporary_type = temporary_function_queue<F&&...>;
using data_type = std::tuple<F&&...>;
// Lifecycle
private:
temporary_function_queue(rvalue_reference) = default;
temporary_function_queue(const_lvalue_reference) = delete;
temporary_function_queue operator=(rvalue_reference) = delete;
temporary_function_queue operator=(const_lvalue_reference) = delete;
explicit constexpr temporary_function_queue(F&&... f)
: _f{std::forward<F>(f)...}
{
}
// Temporary creator
public:
friend constexpr temporary_type apply_function_queue<>(F&&... f);
// Apply function queue declaration
public:
template <class... Args>
decltype(auto) operator()(Args&&... args) const&&
{
// Do I need to do std::forward on f0 too? If so, how?
return std::get<0>(_f)(std::forward<Args>(args)...);
}
// Data members
private:
data_type _f;
};
// Apply function queue definition
template <class... F>
constexpr temporary_function_queue<F&&...> apply_function_queue(F&&... f)
{
return temporary_function_queue<F&&...>(std::forward<F>(f)...);
}
/* Example of use
int main(int argc, char* argv[])
{
apply_function_queue(
[](auto i){std::cout<<0<<std::endl;},
[](auto i){std::cout<<1<<std::endl;}
)(0);
return 0;
}
*/
ç›®æ ‡æ˜¯äº§ç”Ÿä»¥ä¸‹è°ƒç”¨è¯æ³•ï¼š
apply_function_queue(f0, f1, f2)(a, b, c, d, e);
å…¶ä¸f0, f1, f2
是函数指针,仿函数,lambdas ......,其ä¸a, b, c, d, e
是完全转å‘çš„å‚数。æ¤å‡½æ•°åº”生æˆä¸´æ—¶ç±»åž‹ï¼Œç„¶åŽè°ƒç”¨è¯¥ä¸´æ—¶ç±»åž‹çš„operator()
,æ¤è¿ç®—符应完美转å‘fn
(现在为f0
,ç¨åŽå°†æ›´æ”¹ï¼‰ä½¿ç”¨å‚æ•°a, b, c, d, e...
。 temporary_function_queue
ä¸åº”在任何其他环境ä¸ä½¿ç”¨ã€‚
问题是我对转å‘,通用引用和左值引用有点é—失......上é¢æ˜¾ç¤ºçš„代ç 是å¦å®‰å…¨ï¼Ÿå¦‚æžœä¸æ˜¯ï¼Œå“ªç§ä½¿ç”¨ç¤ºä¾‹ä¼šå¯¼è‡´æœªå®šä¹‰çš„行为?在这ç§æƒ…况下,如何使其安全,高效(ç†æƒ³æƒ…况下,我ä¸å¸Œæœ›å¤§å¤šæ•°ç¼–译器使用-O3è¿è¡Œæ—¶å¼€é”€ï¼‰ï¼Ÿ
ç”案 0 :(得分:1)
注æ„:这ç§æ–¹æ³•å¾ˆå¯èƒ½ä¼šå‘生悬空引用。
auto make_f(); // return by value
auto&& q = apply_function_queue(make_f());
// q holds dangling rvalue reference
q(a, b, c); // whoops...
首先是关于措辞和演绎的一些评论。让:
template<class... T> void f(T&&... p) {}
注æ„:实例化æ¤æ¨¡æ¿æ—¶ï¼Œæ¤å¤„有两个ä¸åŒçš„包:T...
å’ŒT&&...
。
使用左值或类型R
和类型为Q
的左值调用它:
R a;
f(a, Q{});
现在T...
将为R&, Q
,但T&&...
将为R&, Q&&
。
转å‘包p
将产生T&&...
包。
'decltype'(std::forward<T>(p)...) === T&&...
(注æ„ï¼šä½ å®žé™…ä¸Šä¸èƒ½åœ¨è¿™é‡Œåº”用decltype - 它仅用于说明。)
å› æ¤ï¼Œæˆ‘将调用实际推æ–出的包(T...
)推导出的类型/包以åŠæ·»åŠ å³å€¼å¼•ç”¨/转å‘(T&&...
)的结果转å‘的类型/包。
在类ä¸çš„任何地方以åŠ&&
的返回类型ä¸åº”用apply_function_queue
都是多余的。 (如果您从temporary_function_queue<F&&...>
返回apply_function_queue
,则&&
å†…æ— éœ€temporary_function_queue
。如果您在课程ä¸åº”用&&
ï¼Œåˆ™æ— éœ€è¿”å›žtemporary_function_queue<F&&...>
。)
您å¯ä»¥ä½¿ç”¨æŽ¨æ–的包实例化类模æ¿ï¼Œå¹¶åœ¨æ‚¨æƒ³è¦å¼•ç”¨çš„ä»»ä½•åœ°æ–¹æ·»åŠ &&
,并使用转å‘包实例化类模æ¿ï¼Œå¹¶ä¸”ä¸è¦æ·»åŠ &&
。
è¦æ±‚åœ¨è¯¾å ‚ä¸Šæ供推æ–出的类型。 ï¼ˆå› ä¸ºå¥½å‹å£°æ˜ŽåŒæ—¶ä½¿ç”¨F...
å’ŒF&&...
ã€‚ï¼‰å› æ¤ï¼Œæ‚¨éœ€è¦ä»Ž&&
的返回类型ä¸åˆ 除apply_function_queue
。
您需è¦æ›´æ”¹ä¸€äº›å£°æ˜Žï¼š
<强> apply_function_queue
强>
å‰çž»å£°æ˜Žï¼š
template <class... F>
constexpr temporary_function_queue<F...> apply_function_queue(F&&... f);
定义:
template <class... F>
constexpr temporary_function_queue<F...> apply_function_queue(F&&... f)
{
return temporary_function_queue<F...>(std::forward<F>(f)...);
}
<强> temporary_type
强>
类实例类型为temporary_function_queue<F...>
而éžtemporary_function_queue<F&&...>
ï¼
using temporary_type = temporary_function_queue<F...>;
朋å‹å£°æ˜Ž
friend constexpr temporary_type apply_function_queue<F...>(F&&... f);
å¦‚æžœä½ æƒ³åœ¨å‡½æ•°è°ƒç”¨æ“作符ä¸å®Œç¾Žè½¬å‘rvalueå‡½æ•°ç±»åž‹ï¼Œæˆ‘è®¤ä¸ºä½ å¿…é¡»æ±‚åŠ©äºŽæ‰‹åŠ¨è½¬æ¢/转å‘。
在decltype(auto) operator()(Args&&... args) const&&
å†…ä½ ä¼šå‘现
decltype(std::get<0>(_f)) === std::tuple_element_t<0u, data_type>&
通过引用折å è§„åˆ™æ˜¯å·¦å€¼å¼•ç”¨ã€‚ä½ çœŸæ£æƒ³è¦çš„是为了转å‘元组ä¸çš„å…ƒç´ æ˜¯tuple_element::type
。
å› æ¤ï¼Œæ‚¨å¿…须直接转æ¢ä¸ºå…ƒç»„ä¸çš„实际类型:
return static_cast<std::tuple_element_t<0u, data_type>>(
std::get<0>(_f))(std::forward<Args>(args)...);
或å‰è¿›ï¼ˆé€šè¿‡å‚考折å 将产生相åŒçš„效果):
return std::forward<std::tuple_element_t<0u, data_type>>(
std::get<0>(_f))(std::forward<Args>(args)...);