以下是代码示例:
#include <string>
#include <functional>
struct Foo {};
typedef bool func_type(Foo *&, const std::string&);
typedef std::function<bool(Foo*&, const std::string&)> FunctionalType;
bool f(Foo *, const std::string&)
{
}
int main()
{
#if 1
func_type *func;
func = f;
#else
FunctionalType f2;
f2 = f;
#endif
}
如您所见,我已声明函数类型为&#34;引用指针&#34;作为第一个参数Foo *&
,我希望该函数只有&#34;指针&#34;因为第一个参数Foo *
不能分配给这种类型的变量。
#if 1
区域无法编译(正如我所料);但是,替代方案没有发出任何错误:
FunctionalType f2;
f2 = f;
为什么编译时没有错误(至少包含gcc 5.2和clang 3.7)?
如何修复它,以便std::function<Params>
不接受f
进行转换?
答案 0 :(得分:4)
std::function<R(Ts...)>
被定义为一种类型,其对象可以表示可以使用参数Ts...
调用并且其返回值可转换为R
的任何函数。
由于您的函数f
可以使用类型为T*
的左值作为第一个参数(这是您的Foo *&
强加的要求)来调用,因此它是一个有效的函数存储在std::function
。
无法抑制我所知道的这种行为。
答案 1 :(得分:3)
std::function
是一个可以调用的东西的类型擦除容器。
它将存储任何C ++类型的实例,可以使用“兼容”签名复制,销毁和调用。
在这种情况下,签名为bool(Foo*&, const std::string&)
。
核心思想是,当Args...
类型的R(Args...)
部分std::function
为Foo*&
,const std::string&
时,的参数可以是已将传递给期望Foo*
和const std::string&
的函数。
std::function
基于兼容性工作,而不是完全匹配签名。
如果你真的,真的需要禁止那些不参考的东西:
template<class T>
struct reference_only {
T& t;
operator T&(){ return t; }
operator T()=delete;
reference_only(T& tin):t(tin){}
};
然后使用:
typedef std::function<void(reference_only<Foo*>)> FunctionalType;
不喜欢转换为值类型,但接受转换为引用类型(在这种情况下类型为Foo*&
)。