idu*_*ree 6 c++ boost tr1 c++11
鉴于:
#include <functional>
class world_building_gun;
class tile_bounding_box;
typedef std::function<void (world_building_gun, tile_bounding_box)> worldgen_function_t;
void foo() {
worldgen_function_t v;
worldgen_function_t w(v);
}
Run Code Online (Sandbox Code Playgroud)
这会编译吗?我的编译器说:
是的:GCC/stdlibc ++(在GCC和Clang中也是boost :: function都是)
No:Clang/libc ++(http://libcxx.llvm.org/,Clang 3.0,libc ++ SVN截至今日)
(如果"no"是正确答案,我将修复我的真实代码,将完整类型放入更多标题或使用boost :: function.)
编辑:这是Clang错误消息:
In file included from foo.cpp:2:
In file included from /usr/include/c++/v1/functional:462:
/usr/include/c++/v1/type_traits:2766:19: error: invalid appli
static_assert(sizeof(_Tp) > 0, "Type must be complete.");
^~~~~~~~~~~
/usr/include/c++/v1/type_traits:2752:15: note: in instantiation of template class 'std::__1::__check_complete<world_buildin
: private __check_complete<_Hp>,
^
/usr/include/c++/v1/type_traits:2753:15: note: in instantiation of template class 'std::__1::__check_complete<world_buildin
private __check_complete<_T0, _Tp...>
^
/usr/include/c++/v1/type_traits:2919:15: note: in instantiation of template class 'std::__1::__check_complete<std::__1::fun
world_building_gun, tile_bounding_box>' requested here
: private __check_complete<_Fp, _Args...>
^
/usr/include/c++/v1/type_traits:2930:11: note: in instantiation of template class 'std::__1::__invokable_imp<std::__1::func
world_building_gun, tile_bounding_box>' requested here
__invokable_imp<_Fp, _Args...>::value>
^
/usr/include/c++/v1/functional:1115:33: note: in instantiation of template class 'std::__1::__invokable<std::__1::function<
world_building_gun, tile_bounding_box>' requested here
template <class _Fp, bool = __invokable<_Fp&, _ArgTypes...>::value>
^
/usr/include/c++/v1/functional:1141:35: note: in instantiation of default argument for '__callable<std::__1::function<void (world_building_gun, tile_bounding_box)> >' required here
typename enable_if<__callable<_Fp>::value>::type* = 0);
^~~~~~~~~~~~~~~
/usr/include/c++/v1/functional:1140:7: note: while substituting deduced template arguments into function template 'function' [with _Fp = std::__1::function<void
(world_building_gun, tile_bounding_box)>]
function(_Fp,
^
foo.cpp:4:7: note: forward declaration of 'world_building_gun'
class world_building_gun;
^
In file included from foo.cpp:2:
In file included from /usr/include/c++/v1/functional:462:
/usr/include/c++/v1/type_traits:2766:19: error: invalid application of 'sizeof' to an incomplete type 'tile_bounding_box'
static_assert(sizeof(_Tp) > 0, "Type must be complete.");
^~~~~~~~~~~
/usr/include/c++/v1/type_traits:2753:15: note: in instantiation of template class 'std::__1::__check_complete<tile_bounding_box>' requested here
private __check_complete<_T0, _Tp...>
^
/usr/include/c++/v1/type_traits:2753:15: note: in instantiation of template class 'std::__1::__check_complete<world_building_gun, tile_bounding_box>' requested here
private __check_complete<_T0, _Tp...>
^
/usr/include/c++/v1/type_traits:2919:15: note: in instantiation of template class 'std::__1::__check_complete<std::__1::function<void (world_building_gun, tile_bounding_box)> &,
world_building_gun, tile_bounding_box>' requested here
: private __check_complete<_Fp, _Args...>
^
/usr/include/c++/v1/type_traits:2930:11: note: in instantiation of template class 'std::__1::__invokable_imp<std::__1::function<void (world_building_gun, tile_bounding_box)> &,
world_building_gun, tile_bounding_box>' requested here
__invokable_imp<_Fp, _Args...>::value>
^
/usr/include/c++/v1/functional:1115:33: note: in instantiation of template class 'std::__1::__invokable<std::__1::function<void (world_building_gun, tile_bounding_box)> &,
world_building_gun, tile_bounding_box>' requested here
template <class _Fp, bool = __invokable<_Fp&, _ArgTypes...>::value>
^
/usr/include/c++/v1/functional:1141:35: note: in instantiation of default argument for '__callable<std::__1::function<void (world_building_gun, tile_bounding_box)> >' required here
typename enable_if<__callable<_Fp>::value>::type* = 0);
^~~~~~~~~~~~~~~
/usr/include/c++/v1/functional:1140:7: note: while substituting deduced template arguments into function template 'function' [with _Fp = std::__1::function<void
(world_building_gun, tile_bounding_box)>]
function(_Fp,
^
foo.cpp:5:7: note: forward declaration of 'tile_bounding_box'
class tile_bounding_box;
^
2 errors generated.
Run Code Online (Sandbox Code Playgroud)
如果删除"worldgen_function_t w(v);"行,Clang + libc ++编译成功 或者如果我使类完成类型.
编辑: 显然,这个问题现已解决,因此下面的文本可以被视为历史。:)
\n问题确实是(正如我所预测的)libc++ 的 SFINAE 检查模板化的 ctor(为了推理,请检查此问题)。它检查以下内容(例如)是否有效,并在施工现场给出一个漂亮且干净的错误,而不是深入内部(尝试使用libstd++或 MSVC 的std::function以下示例...颤抖):
#include <functional>\n\nvoid f(int* p){}\n\nint main(){\n std::function<void(int)> fun(f);\n}\nRun Code Online (Sandbox Code Playgroud)\nlibc++ 将导致编译器吐出类似“没有找到与参数列表匹配的构造函数void (*)(int*)”的内容,因为唯一适用的构造函数(模板化构造函数)会被 SFINAE 删除。
但是,为了使__callable和__invoke_imp检查起作用,参数和返回类型需要完整,否则这里不会考虑隐式转换。
甚至查看模板化 ctor 的原因是,在考虑最佳匹配之前会枚举所有 ctor(在本例中为复制 ctor)。
\nstd::function现在,标准非常明确,从可调用对象构造对象时(也称为调用模板化构造函数),参数和返回类型需要完整:
\xc2\xa720.8.11.2.1 [func.wrap.func.con] p7
template <class F> function(F f);\ntemplate <class F, class A> function(allocator_arg_t, const A& a, F f);\nRun Code Online (Sandbox Code Playgroud)\n\n\n要求:
\nF应为CopyConstructible。对于参数类型和返回类型f应是可调用的(20.8.11.2) 。[...]ArgTypesR
(注意:“要求”针对的是功能的用户,而不是实现者。)
\n\xc2\xa720.8.11.2 [func.wrap.func] p2
\n\n如果表达式被视为未计算的操作数(第 5 条)且格式正确(20.8.2) ,则类型的可调用对象对于参数类型和返回类型
\nf来说是可调用的。FArgTypesRINVOKE(f, declval<ArgTypes>()..., R)
\xc2\xa720.8.2 [func.req]
\n\np1 定义如下:
\nINVOKE(f, t1, t2, ..., tN)\n
\n- \n
(t1.*f)(t2, ..., tN)whenf是指向类的成员函数的指针T,并且t1是类型的对象T或对类型的对象的引用T或对派生自 的类型的对象的引用T;- \n
((*t1).*f)(t2, ..., tN)whenf是指向类的成员函数的指针T,并且t1不是上一项中描述的类型之一;- [...]
\n- \n
f(t1, t2, ..., tN)在所有其他情况下。p2 定义为隐式转换为.
\nINVOKE(f, t1, t2, ..., tN, R)INVOKE(f, t1, t2, ..., tN)R
因此,libc++ 当然有权在模板化构造函数中进行 SFINAE 检查,因为类型需要完整,否则您会得到未定义的行为。然而,即使从不需要实际的 SFINAE 检查(因为复制构造函数总是被调用),完整类型的安全检查也会触发,这可能有点不幸,并且被认为是一个缺陷。这可以通过使callable检查成为惰性检查来缓解,例如
template<bool Copy, class F>\nstruct lazy_callable{\n static bool const value = callable<F>::value;\n};\n\ntemplate<class F>\nstruct lazy_callable<true, F>{\n static bool const value = false;\n};\n\ntemplate<class F>\nfunction(F f, typename enable_if<lazy_callable<!std::is_same<F,function>::value>::type* = 0);\nRun Code Online (Sandbox Code Playgroud)\ncallable如果F实际上不是,这应该只会触发SFINAE 检查std::function<...>。
伙计,我最后可能有点离题了……
\n| 归档时间: |
|
| 查看次数: |
1633 次 |
| 最近记录: |