Captain Normal
Captain Normal

Reputation: 471

Passing a std::array of unknown type and size to a constructor of a templated function

A similar question has been answered for passing to a function in the example referenced here, but this question is about passing a std::array to the constructor of a templated class.

Example of the templated class:

#include <array>

template<typename T, std::size_t N>
class Pipeline {
public:
    Pipeline(std::array<T, N>& buffer);
...

Example of a call to this constructor which works:

std::array<uint16_t, 100> buffer;
Pipeline<uint16_t, buffer.size()> pipeline(buffer);

I find that ugly because the information about the buffer, both the type and length, is effectively duplicated in the call. Here is what I would like to do:

std::array<uint16_t, 100> buffer;
Pipeline pipeline(buffer);

That is not allowed, although the same technique used with a call to a templated function (instead of the constructor of a templated class) is allowed.

Is there a way to define the constructor such that the call I would like to do is allowed?

Upvotes: 0

Views: 213

Answers (2)

Jarod42
Jarod42

Reputation: 217145

As state in comment, in C++17 it's valid to use:

std::array<uint16_t, 100> buffer;
Pipeline pipeline(buffer); // Pipeline<uint16_t, 100>

Earlier than C++17 you need to use a helper function:

template <typename T, std::size_t N>
Pipeline<T, N> make_pipeline(std::array<T, N>& buffer)
{
    return Pipeline<T, N>(buffer);
}

auto pipeline = make_pipeline(buffer); // Pipeline<uint16_t, 100>

That assumes that your class is move (or copy) constructable.

Upvotes: 3

Paolo Brandoli
Paolo Brandoli

Reputation: 4750

Before C++17, a bit of acrobatic can give you what you want:

#include <iostream>

#include <array>

template<typename T, std::size_t N>
class Pipeline
{
    public:
    Pipeline(std::array<T, N>& buffer)
    {
        for(size_t scan(0); scan != buffer.size(); ++scan)
        {
            std::cout << buffer[scan] << std::endl;
        }
    }
};

int main()
{
    std::array<int, 10> array({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});

    Pipeline<std::tuple_element<0, decltype(array)>::type, std::tuple_size<decltype(array)>::value> test(array);

    return 0;
}

Upvotes: 0

Related Questions