通过模板模板类数组的参数推导进行隐式初始化

时间:2020-09-01 02:06:41

标签: c++ templates initialization aggregate-initialization copy-initialization

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

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

这里的项目类是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;
    }
};

这里有模板化的Node类

#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

1 个答案:

答案 0 :(得分:4)

在数组的aggregate initialization中,元素是来自初始化程序列表的相应子句中的copy-initialized。这意味着类型bNode<bItem>的元素需要从int复制初始化,这需要两次用户定义的隐式转换,从intbItem和{{ 1}}到bItem,这是不允许的。

每个bNode数组元素或非静态类成员,按类定义中数组下标/外观的顺序,位于初始化器列表的相应子句中copy-initialized

作为解决方法,您可以限制隐式转换的时间,例如

direct public base, (since C++17)

或者您可以在bNode<bItem> nodes[5] = { bItem(1),bItem(2),bItem(3),bItem(4),bItem(5) }; 中添加另一个使用int的构造函数,然后也可以从bNode复制初始化。

int

BTW:// forward it to bNode::bNode(itemType) bNode(int val) : bNode(itemType(val)) {} 执行direct initialization,仅需要一次隐式转换(从bNode<bItem> node2(6);int),然后将转换后的bItem传递给bItme的构造函数以构造bNode。它没有copy initialization这样的问题。 (像node2这样的复制初始化也不起作用。)

此外,复制初始化中的隐式转换必须直接从初始值设定项产生T,而例如直接初始化需要从初始值设定项到T的构造函数的参数的隐式转换。

相关问题