通过模板化 class 数组的参数推导隐式初始化

Implicit initialization by argument deduction for a templated class array

我有一个项目 class,它实际上是一个 int 的包装器。 我有一个模板化节点 class。我将项目 class 作为模板参数传递给它。

我想创建一个模板节点数组 class,但编译器不喜欢它。 当我使用相同的语法创建单个对象时,它起作用了。 为什么它不能推断数组元素来初始化模板化数组class? 创建模板化对象数组的正确方法是什么 class?

这是项目 class,它是 int.

的包装
using namespace std;

class bItem {
private :     
    int item{INT_MIN};
public:
    bItem() : item(INT_MIN) {}
    bItem(int val) : item(val) {}
    int getItem() { return item; }
    bItem operator==(const bItem& val) {
        return item == val.item;
    }
    bItem operator>(const bItem& val) {
        return item > val.item;
    }
    bItem operator<(const bItem& val) {
        return item < val.item;
    }
    friend ostream& operator<<(ostream& os, const bItem& item) {
        os << "value:" << item.item << endl;
        return os;
    }
};

这是模板节点 class

#include <iostream>
using namespace std;
template<class itemType>
class bNode {
    itemType item{};
    bNode* prev{};
    bNode* next{};
public:
    bNode() : item(), prev(nullptr), next(nullptr) {}
    bNode(itemType _item) : item(_item), prev(nullptr), next(nullptr) {}
    ~bNode() {
        delete prev;
        delete next;
    }
    
    friend ostream& operator<<(ostream& os, const bNode& node) {
        os << "node " << node.item<< endl;
        return os;
    }
};

这里是 main()

int main()
{    
    bNode<bItem> nodes[5]{ 1,2,3,4,5 }; //this does not compile
    bNode<bItem> node2(6); //this compiles ok

}

这是错误信息

error C2440: 'initializing': cannot convert from 'int' to 'bNode<bItem>'
message : No constructor could take the source type, or constructor overload resolution was ambiguous

In aggregate initialization of array, the elements are copy-initialized 来自初始值设定项列表的相应子句。这意味着类型为 bNode<bItem> 的元素需要从 int 变为 copy-initialized,这需要两次 user-defined 隐式转换,从 intbItembItembNode,这是不允许的。

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.

作为解决方法,您可以对隐式转换的次数施加限制,例如

bNode<bItem> nodes[5] = { bItem(1),bItem(2),bItem(3),bItem(4),bItem(5) };

或者你可以添加另一个从 intbNode 的构造函数,那么它也可以是 int 的 copy-initialized。

// forward it to bNode::bNode(itemType)
bNode(int val) : bNode(itemType(val)) {}

顺便说一句:bNode<bItem> node2(6); 执行 direct initialization, which requiers only one implicit conversion (from int to bItem), and the converted bItme is passed to the constructor of bNode to construct node2. It doesn't have such issue as copy initialization。 (Copy-initialization 像 bNode<bItem> node2 = 6; 也不起作用。)

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.