在 std::array 中使用时无法从 std::function 构造 class
Can not construct a class from std::function when used inside std::array
我想要 std::function
的 std:array
,但我想确保数组的所有元素都已初始化。
为此,我构建了一个包装器 class,它将 std::function
作为构造参数。
但是当我直接用我的函数(应该在 std::function
中的函数)初始化包装器 class 的数组时,它无法编译。
这是问题所在,经过提炼:
#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 = f;
(即 direct initialization), in aggregate initialization, every element is copy initialized。
Each direct public base, (since C++17)
array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
这意味着,wrapper
的最后一个元素,类型为 C
,是从 f
复制初始化的;这需要两次隐式转换。从函数指针到F
的转换,以及从F
到C
的转换。两者都是自定义转换,但一个隐式转换序列中只允许有一个自定义转换。
出于同样的原因 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 and behaves differently with copy initialization。对于直接初始化,将考虑 C
的构造函数,其中之一需要一个 F
作为参数,f
可以转换为 F
那么一切都很好;这里只需要一个用户定义的转换。
(强调我的)
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.
我想要 std::function
的 std:array
,但我想确保数组的所有元素都已初始化。
为此,我构建了一个包装器 class,它将 std::function
作为构造参数。
但是当我直接用我的函数(应该在 std::function
中的函数)初始化包装器 class 的数组时,它无法编译。
这是问题所在,经过提炼:
#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 = f;
(即 direct initialization), in aggregate initialization, every element is copy initialized。
Each
direct public base, (since C++17)
array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
这意味着,wrapper
的最后一个元素,类型为 C
,是从 f
复制初始化的;这需要两次隐式转换。从函数指针到F
的转换,以及从F
到C
的转换。两者都是自定义转换,但一个隐式转换序列中只允许有一个自定义转换。
出于同样的原因 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 and behaves differently with copy initialization。对于直接初始化,将考虑 C
的构造函数,其中之一需要一个 F
作为参数,f
可以转换为 F
那么一切都很好;这里只需要一个用户定义的转换。
(强调我的)
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.