4

考虑一个封装了其他函数但在封装调用之后执行某些操作的函数。

template< typename ftor, typename ... args >
typename std::result_of< ftor( args ... ) >::type
call_and_report( ftor && f, args && ... a ) {
    auto && ret{ f( std::forward< args >( a ) ... ) };
    std::cout << "Done!\n";
    return std::forward< typename std::result_of< ftor( args ... ) >::type >
                       ( ret );
}

如何扩展它以包装返回的函数void?添加另一个专业很容易,但我正在寻找另一种可能是惯用的方式。

一般的想法是可能有也可能没有价值。这就像 compile-time optional

4

3 回答 3

4

执行函数返回是合法的:

template <typename F, typename ... Args>
auto call_and_report(F && f, Args && ... a) 
    -> decltype(f(std::forward<Args>(a)...))
{
    return f(std::forward<Args>(a)...);
}

现在要在调用后执行某些操作,您可以在对象的析构函数中执行此操作:

template <typename F, typename ... Args>
auto call_and_report(F && f, Args && ... a) 
    -> decltype(f(std::forward<Args>(a)...))
{
    struct execute { ~execute() { std::cout << "Done!" << '\n'; } } execute;
    return f(std::forward<Args>(a)...);
}
于 2013-09-16T08:26:34.667 回答
1

最简单的方法是在本地对象的析构函数中执行附加代码。这样做也允许直接传递结果,这可以省略复制/移动,否则需要 fir 非左值返回:

template <typename F, typename... Args>
...
call_and_forward(F&& f, Args&&... args) {
    struct report {
        ~report() { std::cout << "done\n"; }
    } reporter;
    return f(std::forward<Args>(args)...);
}
于 2013-09-16T08:38:08.460 回答
0

这是将问题以至少可以重用的形式转移到专用包装器的尝试。

不确定正确性,甚至没有尝试编译一次。至少,在static_cast按值返回时会进行不必要的复制。

我只是出于好奇而这样做,实际上并不需要解决这个问题,但它看起来相当繁重。

template< typename ftor, typename ... args >
typename std::enable_if< ! std::is_void< typename std::result_of< ftor( args ... ) >::type >::value,
    typename std::result_of< ftor( args ... ) >::type >::type
call_or_wrap_void( ftor && f, args && ... a )
    { return std::forward< ftor >( f ) ( std::forward< args >( a ) ... ); }

struct void_wrapper {};

template< typename ftor, typename ... args >
typename std::enable_if< std::is_void< typename std::result_of< ftor( args ... ) >::type >::value,
    void_wrapper >::type
call_or_wrap_void( ftor && f, args && ... a ) {
    std::forward< ftor >( f ) ( std::forward< args >( a ) ... );
    return {};
}

template< typename ftor, typename ... args >
typename std::result_of< ftor( args ... ) >::type
call_and_report( ftor && f, args && ... a ) {
    auto && ret{ call_or_wrap_void( std::forward< ftor >( f ), std::forward< args >( a ) ... ) };
    std::cout << "Done!\n";
    return static_cast< typename std::result_of< ftor( args ... ) >::type >
                      ( std::move( ret ) );
}
于 2013-09-16T09:02:53.423 回答