c++ - 允许为所有数组元素调用任何构造函数

标签 c++

经过一些调查,看起来初始化变量的行为遵循一些约定。

对于单个元素:

auto* x = new int; // undefined value
auto* x = new int{}; // 0 (default initializer)
auto* x = new int(23); // 23 (copy initializer)

auto* x = new Test; // default constructor
auto* x = new Test{}; // default constructor
auto* x = new Test(...); // X constructor (overload-chosen)

这很有意义,除非您尝试在数组上应用相同的逻辑:

auto* x = new int[10]; // all undefined values - OK
auto* x = new int[10]{}; // all 0 (default initializer) - OK
auto* x = new int[10](23); // all 23 (copy initializer on all) - NOT IMPLEMENTED

auto* x = new Test[10]; // default constructors - OK
auto* x = new Test[10]{}; // default constructors - OK
auto* x = new Test[10](...); // X constructor on all (overload-chosen) - NOT IMPLEMENTED

我的逻辑是你可以做一些假设:

  • 如果可以使用 T(Args..) 构造类型,则可以构造数组中的每个元素。没有理由不允许 T[N](Args...) 语法。

有谁知道为什么这个功能不存在?允许的话会非常好

new int[10](23); // all 23
new Test[10]("asd", 123); // construct all using Test("asd", 123)

编辑:整个想法是避免默认的初始化/构造函数并直接调用我们需要的那个。

最佳答案

如果标准库中有这方面的东西就好了,您想要的功能实现起来相对简单:

namespace detail {
    template<typename T, typename... ArgTs, std::size_t... Is>
    constexpr auto make_filled_array(ArgTs const&... args, std::index_sequence<Is...>)
    -> std::array<T, sizeof...(Is)> {
        return {{(Is, T(args...))...}};
    }
}

template<typename T, std::size_t N, typename... ArgTs, std::enable_if_t<N != 0, int> = 0>
constexpr auto make_filled_array(ArgTs const&... args) {
    return detail::make_filled_array<T, ArgTs...>(args..., std::make_index_sequence<N>{});
}

// ...

auto arr1 = make_filled_array<int, 10>(23);
auto arr2 = make_filled_array<Test, 10>("asd", 123);

Online Demo

就是说,我认为在这里使用构造函数参数没有任何意义;容器emplace函数很有用,因为它们可以进行完美转发,但我们不能在这里这样做,因为我们需要为每个构造函数调用重用参数(因此从它们转移不是一种选择)。我认为复制构造是自然的:

namespace detail {
    template<typename T, std::size_t... Is>
    constexpr auto make_filled_array(T const& t, std::index_sequence<Is...>)
    -> std::array<T, sizeof...(Is)> {
        return {{(Is, t)...}};
    }
}

template<std::size_t N, typename T, std::enable_if_t<N != 0, int> = 0>
constexpr auto make_filled_array(T const& t) {
    return detail::make_filled_array(t, std::make_index_sequence<N>{});
}

// ...

auto arr1 = make_filled_array<10>(23);
auto arr2 = make_filled_array<10>(Test{"asd", 123});

Online Demo

注意您对 new 的使用暗示您可能来自托管语言并且需要阅读值语义。 ;-] 此代码可以 更改为返回 std::array<T, N>*T* (甚至是 std::unique_ptr<T[]> 适度合理的东西),但是,为什么会有一个..?只需使用 std::vector<T> :

std::vector<int> vec(10, 23);

我选择演示std::array<>在这里是因为您的示例都具有恒定大小。


想到的最接近的是 std::fill ,但这不会初始化数组...

关于c++ - 允许为所有数组元素调用任何构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48610895/

相关文章:

c++ - 为什么 argc 返回 6 而不是 3?

c++ - 你会如何改进这个算法? (c 弦反转)

c++ - 更改数据忽略 const 限定符

C++ 慢,python 快? (就开发时间而言)

c++ - 在 C++ 中读取 kinect 深度文件

c++ - QDialog::move() 不考虑具有多个屏幕的 Ubuntu 上的任务栏

c++ - 试图绘制点云,只是 opengl 中心的一个点

c++ - C的 "extern"是怎么工作的?

c++ - 忽略 vector C++ 中的空格

c++ - WPD API - 无法从设备传输内容(包括 SSCCE)