c++ - 在 C++11 中,我可以为非聚合类型实现类似构造函数的聚合类型初始化吗?如何实现?

标签 c++ c++11 templates

比如说,我有一个封装在名为 stA

的类中的一维数组
class stA
{
public:
    template<typename ... T>
    stA(T ... t):
        data_{t...}
    {}

private:
    int data_[2];
};

通过利用可变参数模板,我可以成功实现这个想法。

stA a = {1, 2};

但是,当我试图将这个技巧应用于名为 stB 的类二维类时,

class stB
{
public:
    template<typename ... T>
    stB(T ... t):
        data_{t...}
    {}

private:
    stA data_[2];
};

诡计失败了。

stB b = {{1, 2}, {1, 2}};

error: could not convert '{{1, 2}, {1, 2}}' from brace-enclosed initializer list to 'stB' stB b = {{1, 2}, {1, 2}};

一开始这让我很困惑。

因为如果 stB::Ctor 中的 template-argument-deduction 导致 T = const stA &,那么 Ctor 会变成这样,

stB(const stA & a, const stA & b):
        data_{a, b}
    {}

当然 stB b = {{1, 2}, {1, 2}}; 会存活下来,但会失去一些参数的灵 active 。

经过一番搜索,我终于意识到这可能违反了模板参数推导的规则,

Non-deduced contexts

6) The parameter P, whose A is a braced-init-list, but P is not std::initializer_list, a reference to one (possibly cv-qualified), or a reference to an array:

但我还在徘徊 是否还有办法实现这个想法?如何实现?

最佳答案

问题是 {1, 2} 不是表达式,只能推导表达式。

选项 1:使用聚合初始化。使 data_ 成员公开,聚合初始化允许您初始化元素。缺点:控制力差。

选项 2:使用 initializer_list。如:

class stA {
public:
    stA(std::initializer_list<int> init):
        data_{init.begin()[0], init.begin()[1]}
    {
        assert(init.size() == 2);
    }

private:
    int data_[2];
};

class stB {
public:
    stB(std::initializer_list<std::initializer_list<int>> init):
        data_{init.begin()[0], init.begin()[1]}
    {
        assert(init.size() == 2);
    }

private:
    stA data_[2];
};

缺点:大小信息在编译时丢失。

选项 3:使用聚合类型作为构造函数参数。

class stA {
public:
    stA(const int (&arr)[2]):
        data_{arr[0], arr[1]}
    {
    }

private:
    int data_[2];
};

class stB {
public:
    stB(const int (&arr)[2][2]):
        data_{arr[0], arr[1]}
    {
    }

private:
    stA data_[2];
};

(这需要一对额外的大括号,如 stB b = {{{1, 2}, {3, 4}}};。)

关于c++ - 在 C++11 中,我可以为非聚合类型实现类似构造函数的聚合类型初始化吗?如何实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57252228/

相关文章:

c++ - "lost"堆栈对象发生了什么?

c++ - 只读取二进制 zip 文件的一部分

c++ - 将指针 push_back 到指针 vector 中是内存泄漏吗?

c++ - 获取 std::map 中的最小键

Java 等效于 C++ 模板 <int val> class foo{ };

c++ - 同名类之间的共享 vtables : call to virtual method crashes when casting to base type

c++ - 如何使用 cmake 在 OSX 上编译 glfw

c++ - 模拟 const 值以进行测试

c++ - 启用_if : case of templated method of a template base inherited several times

c++ - 模板类参数类型的模板类成员特化