根据C ++ 11或C ++ 14标准,代码是否在C ++下有效?
#include <functional>
int ReturnInt()
{
return 5;
}
int main( int argc, char **argv )
{
std::function< void () > BoundType = ReturnInt;
return 0;
}
使用最新的cygwin版本的gcc(4.8.3)和clang(4.3.2)编译代码,但不能使用Visual Studio 2013,Visual Studio 2013年11月的CTP或Visual Studio 14预览。如果将std :: function更改为boost :: function,它也会在所有平台上编译。
我发现this其他堆栈溢出问题表明它应该有用。
答案 0 :(得分:9)
代码在C ++ 11中是未定义的行为,在C ++ 14中是不正确的。 C ++ 14将此备注添加到此构造函数的规范中:
备注:这些构造函数不应参与重载 解析除非
f
是可调用的(20.9.11.2)参数类型ArgTypes...
并返回R
类型。
Callable在[func.wrap.func] / p2:
中定义
f
类型的可调用对象F
对于参数类型ArgTypes
是 Callable 如果表达式 INVOKER
,则返回类型(f, declval<ArgTypes>()..., R)
,被视为未评估的操作数 (第5条),形成良好(20.9.2)。
为了使 INVOKE 格式正确,没有R
的 INVOKE 的返回类型必须隐式转换为R
([func] .require] / P2)。
在C ++ 11中,这些语句属于 Requries 子句,这意味着由客户端决定是否正确,如果客户端失败,任何事情都可能发生,包括成功编译。
LWG 2132改变了这一点。
答案 1 :(得分:3)
std::function
没有你想要的行为。
它也无法通过SFINAE检测到错误的重载。
我们可以将它包装在一个不同的类型中,它们都具有您想要的行为(void
丢弃返回)并且我们按照以下方式进行SFINAE严重过载检测:
template<class Sig>
struct checked_function;
template<class R, class... Args>
struct checked_function<R(Args...)>:std::function<R(Args...)> {
using function = std::function<R(Args...)>;
checked_function(std::nullptr_t):function() {}
checked_function():function() {}
template<class F, class=typename std::enable_if<
std::is_convertible<
typename std::result_of< F(Args...) >::type
, R
>::value
>::type>
checked_function( F&& f ):function( std::forward<F>(f) ) {}
template<class F, class=typename std::enable_if<
std::is_convertible<
typename std::result_of< F(Args...) >::type
, R
>::value
>::type>
checked_function& operator=( F&& f ) { return function::operator=( std::forward<F>(f) ); }
checked_function& operator=( checked_function const& o ) = default;
checked_function& operator=( checked_function && o ) = default;
checked_function( checked_function const& o ) = default;
checked_function( checked_function && o ) = default;
};
template<class... Args>
struct checked_function<void(Args...)>:std::function<void(Args...)> {
using function = std::function<void(Args...)>;
checked_function(std::nullptr_t):function() {}
checked_function():function() {}
template<class F, class=typename std::enable_if<
std::is_same<
typename std::result_of< F(Args...) >::type
, void
>::value
>::type>
checked_function( F&& f, int*unused=nullptr ):function( std::forward<F>(f) ) {}
template<class F>
static auto wrap(F&& f){
return [f_=std::forward<F>(f)](auto&&...args){
f_( std::forward<decltype(args)>(args)... );
};
}
template<class F, class=typename std::enable_if<
!std::is_same<
typename std::result_of< F(Args...) >::type
, void
>::value
>::type>
checked_function( F&& f, void*unused=nullptr ):
function( wrap(std::forward<F>(f)) ) {}
template<class F>
typename std::enable_if<
!std::is_same<
typename std::result_of< F(Args...) >::type
, void
>::value,
checked_function&
>::type operator=( F&& f ) { return function::operator=( wrap(std::forward<F>(f)) ); }
template<class F>
typename std::enable_if<
std::is_same<
typename std::result_of< F(Args...) >::type
, void
>::value,
checked_function&
>::type operator=( F&& f ) { return function::operator=( std::forward<F>(f) ); }
checked_function& operator=( checked_function const& o ) = default;
checked_function& operator=( checked_function && o ) = default;
checked_function( checked_function const& o ) = default;
checked_function( checked_function && o ) = default;
};
它现在在C ++ 14中编译(不是在C ++ 11中,由于wrap
:wrap
可以在调用时用自己的主体副本替换,所以.. )。可能会减少一堆样板。
它使用了一些C ++ 14特性(在wrap
中精确地移动到lambda中 - 您可以通过添加更多样板来消除它。)
尚未运行。