c++ - std::is_convertible 与 std::function 不一致

标签 c++ gcc c++11 std

当涉及 std::function 对象和 std::bind 时,我注意到 std::is_convertible 和 std::is_assignable 有一些奇怪的结果。

我假设当这些函数返回 true 时,可以进行转换。还是我遗漏了什么?

以下代码在不同的编译器上打印不同的结果,我希望它打印 0,因为这些类型无法分配。

#include <type_traits> 
#include <functional> 
#include <iostream> 

int main()
{
    std::cout << std::is_convertible<std::function<void(int)>, std::function<void()>>::value << std::endl;
}

它在以下编译器上打印 0:

  • gcc 4.8 和 gcc 4.9
  • clang 3.4(但不是来自 ubuntu 12.04 的那个)

它在以下编译器上打印 1:

  • 海湾合作委员会 4.7
  • VC++12 (VS2013)
  • clang 3.2

有没有正确答案? 这些是编译器中的错误还是我弄乱了特定于编译器的东西?

最佳答案

在 C++11 中,std::function采用任意仿函数类型的构造函数指定为(引用 N3337 §20.8.11.2.1 [func.wrap.func.con]/p7):

template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);

7 Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes and return type R. The copy constructor and destructor of A shall not throw exceptions.

违反 Requires 子句(传递 f 而不是 Callable 参数类型 ArgTypes 和返回类型 R )是未定义的行为,因此库可以自由地做任何事情在那种情况下它想要。该库可能会将构造函数从重载决议中移除,但它不是必须的,如果不是,那么你将遇到重载决议和 std::is_convertible 的问题。 - 它将报告几乎所有在阳光下的东西都可以转换为 std::function (包括 double 之类的东西!)。

因此,在 LWG issue 2132 , 如果仿函数不是 Callable,标准被修改为要求实现从重载解析中删除这些构造函数(通过 SFINAE 或类似技术)对于指定的参数类型和返回类型。现在是:

template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);

7 Requires: F shall be CopyConstructible.

8 Remarks: These constructors shall not participate in overload resolution unless f is Callable (20.9.11.2) for argument types ArgTypes... and return type R.

所以如果你的标准库实现了这个解析,那么std::is_convertible<std::function<void(int)>, std::function<void()>>::valuefalse .否则,它取决于实现。

I would assume that when these functions return true, the conversion can be made. Or am I missing something?

类型特征,例如 std::is_convertible , std::is_constructible , 或 std::is_assignable只考虑直接上下文——即是否存在可访问且未删除的匹配函数签名。它们不检查函数体在实例化时是否会编译。

关于c++ - std::is_convertible 与 std::function 不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25879865/

上一篇:C++ 限制语义

下一篇:C++ std::atomic union

相关文章:

c++ - 这个递归函数的时间复杂度是多少?

c++ - 在 OpenGL 中绘制 N 角星 - C++

c++ - Lambda 捕获数组元素失败

c++ - 如何使用 std::array 模拟 C 数组初始化 "int arr[] = { e1, e2, e3, ... }"行为?

c++ - 从 Python 调用 C/C++?

c++ - 我需要宏还是可以使用模板来执行此操作

c - 是否可以在 Mac 上编译可在 Windows 上编译的 c 程序?

gcc - 无法将 portaudio 库链接为静态库

c++ - 对我的类(class)实现删除功能

C++11 线程 : notify_all() or notify_one() when I only have one?