这个问题本身可能令人困惑,所以我将在这里详细描述它。假设我们有一个类型的S,它表示一个一维向量(线性代数,而不是std )。因为它是一个数组,所以如果它的行为类似于std::array<int, 1>,那就很好了。显然,我们不希望只使用标量进行构造,但是应该允许从单个元素进行隐式列表初始化。下面的代码片段是几个初始化/转换场景,我希望在拒绝#1和#3的同时使用#2和#4。
struct S
{
explicit(?) S(int value);
};
S f1() { return 0; } // #1
S f2() { return { 0 }; } // #2
void g()
{
S s1 = 0; // #3
S s2{ 0 }; // #4
}使构造函数explicit不允许#1和#3,这很好,但副作用是,它也不允许在这个场景中允许#2. #2,就像std::array<int, 1>的工作方式一样。
由于该类型将定义其他构造函数,而且我希望数据是私有的,所以AFAIK不可能使用与std::array (聚合init +大括号)相同的技术。是否有办法达到这一目标?我不介意一定要用些诡计。
谢谢!
编辑:
explicit(false) S(std::array<int, 1>);,它可以工作,但是它需要为#2和#4的案例增加一对支撑。如果没有额外的支撑就能达到同样的目标,那就太好了。发布于 2021-09-02 02:13:45
这是不可能的由于S不是聚合且初始化项列表不是空的,所以直接考虑构造函数 for return {0};。这与return 0;的(非列表)副本初始化相同,只是显式构造函数是不允许的,而不是忽略的。
奇怪的是,这意味着您可以有反向行为:通过提供一个隐式和显式构造函数,这些构造函数对于从int进行构造来说是不明确的,您可以使return {0};因不明确而失败,同时让return 0;选择转换构造函数。
您可能会尝试一个涉及intermediate类型的技巧:
struct hold {hold(int);};
struct S {
S(hold);
};不幸的是,多个用户定义的转换的规则在复制和复制列表初始化之间也是一致的,因此S(hold(0))解释不会在任何一种构造模式下尝试。(在某些情况下,多个级别的大括号允许多个用户定义的转换,但根据假设,这与此无关。)
https://stackoverflow.com/questions/69011701
复制相似问题