在std :: vector中使用时无法从std :: function构造一个类

问题描述 投票:1回答:1

我想将std:array设置为std::function,但是我想确保数组的所有元素都已初始化。为此,我构建了一个包装器类,该包装器类将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<C>(尽管它违背了使用std:array的全部目的,并且拒绝编译上述任何初始化方法。

c++ c++11 std-function stdarray
1个回答
3
投票

问题出在aggregate initialization中,每个元素均复制初始化

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

这意味着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)
};

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

(重点是我的)

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

© www.soinside.com 2019 - 2024. All rights reserved.