初始化一个包含非平凡构造对象的数组

3
我有一个名为Foo的类,需要引用才能构建(它将用于在该内存空间上操作)。
template<typename T>
class Foo {
  public:
    Foo(T& value) : _value(value) {}
    ...
  private:
    T& _value;
};

我还拥有多个 T 的线性内存空间实例。
std::array<T, SIZE> buffer;

我想要构建的是一个Foo对象数组,它映射了我的缓冲区的不同实例。这意味着每个Foo实例都必须使用正确的引用来构建。
std::array<Foo<T>, SIZE> operators;

然而,operators不能被轻松地初始化,我可以通过通过'Foo'构造函数将缓冲区映射来构建它。

有没有什么办法可以做到?我尝试使用 std::forwardstd::initializer_list 但是这些都不能从我的缓冲区构建。

请注意,出于通信目的,我需要保持缓冲区对齐,并且我最终会重载Foo类以为数组的不同元素实现不同的行为。

4个回答

2

std::array 在初始化时必须知道如何构造引用。建议使用指针,例如:

template<typename T>
class Foo {
  public:
    Foo() { } // used by std::array to create Foo<T>
    Foo(T& value) : _value(&value) {}
    operator T&() { return *_value; } // never call this on uninitialised objects
  private:
    T* _value = nullptr;
};

您可以创建一个静态对象来预初始化您的引用。
template<typename T>
class Foo {
  static T _default; // default-object used to initialize the reference
  public:
    Foo() { } // used by std::array to create Foo<T>
    Foo(T& value) : _value(value) {}

    T& _value = _default;
};

int a = 0;
std::array<Foo<int>, 10> arr;
arr[0]._value = a;

1

很遗憾,没有直接初始化operators数组的方法。

我能想到的唯一解决方案是使Foo具有默认构造函数,然后使用循环或例如std::transform遍历buffer并使用赋值“初始化”operators中的每个条目。

类似于:

template<typename T, std::size_t N>
void initialize_operators(const std::array<T, N>& buff,
                          std::array<Foo<T>, N>& ops)
{
    std::transform(std::begin(buf), std::end(buff), std::begin(ops),
                   [](const T& t) { return Foo<T>(t); });
}

0
一种方法是逐个列出初始化器元素:
T a, b;

std::array<Foo<T>, 5> a = { {
    Foo<T>(a), Foo<T>(b), Foo<T>(a), Foo<T>(b), Foo<T>(a) } };

另一种方法是将存储与对象构造分开,并手动管理数组元素的生命周期。

@Amxx:你能否更新你的问题,包括一个具体的期望使用案例? - Kerrek SB

0
这是一个使用索引技巧构建数组的示例:
#include <array>
#include <iostream>

template<typename T>
class Foo {
    public:
        Foo(T& value) : _value(value) {}
        ...
    private:
        T& _value;
};

// Typical varadic indices builder
template<size_t... Is> struct Indices { };

template <size_t count,size_t... Is>
struct BuildIndices : BuildIndices<count-1,count-1,Is...> { };

template<size_t... Is>
struct BuildIndices<0,Is...> : Indices<Is...> { };


// Helper function
template <typename T,size_t... Is>
static std::array<Foo<T>,sizeof...(Is)>
    make_foo_array_with_indices(
            std::array<T,sizeof...(Is)> &values,
            Indices<Is...>
            )
{
    return {{values[Is]...}};
}

template <typename T,size_t count>
static std::array<Foo<T>,count>
    make_foo_array(std::array<T,count> &values)
{
    return make_foo_array_with_indices(values,BuildIndices<count>());
}


int main()
{
    std::array<int,4> buffer = {3,1,4,1};
    std::array<Foo<int>,4> operators = make_foo_array(buffer);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接