【问题标题】:Can not construct a class from std::function when used inside std::array在 std::array 中使用时无法从 std::function 构造类
【发布时间】:2019-10-30 07:37:36
【问题描述】:

我想拥有std::functionstd:array,但我想确保数组的所有元素都已初始化。 为此,我构建了一个将std::function 作为构造参数的包装类。

但是,当我直接使用我的函数(应该在 std::function 中的那个)初始化包装类的数组时,它无法编译。

这是问题,提炼:

#include <functional>
#include <array>

static void f() {}
using F = std::function<void(void)>;
enum { Count = 4 };

struct C
{
    //To get a compilation error when some
    //  elements of the array are not initialized.
    C() = delete;

    C(F) {}
};

//OK
static const C c {f};

//OK
static const std::array<F,Count> direct
{
    F{f},
    {f},
    f,
    f
};

static const std::array<C,Count> wrapper
{
    F{f},   //OK
    C{f},   //OK
    {f},    //OK
    f       //could not convert 'f' from 'void()' to 'C'
};

我尝试将数组更改为 std::vector&lt;C&gt;(尽管它违背了我使用 std:array 开头的全部目的)并且它拒绝编译上述任何初始化。

【问题讨论】:

标签: c++ c++11 initialization std-function stdarray


【解决方案1】:

C c = f;(即direct initialization)不同,aggregate initialization 中的每个元素都是copy initialized

每个direct public base, (since C++17) 数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,是初始化器列表相应子句中的copy-initialized

这意味着wrapper 的最后一个元素,即C 类型,是从f 复制初始化的;这需要两个隐式转换。从函数指针到F的转换,以及从FC的转换。两者都是自定义转换,但一个隐式转换序列中只允许有一个自定义转换。

出于同样的原因,C c = f; 也失败了。

您可以添加显式转换。例如

static const std::array<C,Count> wrapper
{
    F{f},   //OK
    C{f},   //OK
    {f},    //OK
    static_cast<F>(f)
};

static const C c {f}; 有效,因为它是 direct initialization,并且与 copy initialization 的行为不同。对于直接初始化,将考虑C 的构造函数,其中一个期望F 作为参数,f 可以转换为F 然后一切都很好;这里只需要一次用户定义的转换。

(强调我的)

此外,复制初始化中的隐式转换必须直接从初始化程序生成 T,而例如直接初始化期望从初始化程序隐式转换为 T 的构造函数的参数

【讨论】:

    猜你喜欢
    • 2020-09-22
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 2016-02-16
    相关资源
    最近更新 更多