Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduce std::array size?

Tags:

c++

c++14

In the following code:

template<size_t N>
int b(int q, const std::array<int, N>& types)
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

int main()
{
    b<2>(9, { 2,3 });
}

How can I avoid having to specify 2 in the call to b for N? Why can't this type be automatically deduced? With out it I get the error:

'b': no matching overloaded function found 'int b(int,const std::array &)': could not deduce template argument for 'N'

like image 950
paulm Avatar asked Oct 08 '16 14:10

paulm


People also ask

Is std :: array fixed size?

std::array is a container that encapsulates fixed size arrays. This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member. Unlike a C-style array, it doesn't decay to T* automatically.

How do I reduce the size of an array in CPP?

Once an array has been allocated, there is no built-in mechanism for resizing it in the C++ programming language. Therefore, we can avoid this problem by dynamically generating a new array, copying over the contents, and then deleting the old array.

What does size return in array?

array::size() size() function is used to return the size of the list container or the number of elements in the list container.


2 Answers

C++17 std::array class template argument deduction (CTAD)

Starting with C++17, this new language feature is now used by the standard library and now allows us to omit the template types as well so that the following works:

main.cpp

#include <array>

int main() {
    std::array a{1, 2, 3};
}

instead of std::array<int, 3> a{1, 2, 3};

Tested with:

g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp

If we set -std=c++14 instead for example, it fails to compile with:

error: missing template arguments before ‘a’

Tested on Ubuntu 18.04, GCC 7.5.0.


Template argument deduction relies on direct type matching between actual argument and formal argument. The actual argument is an initializer list. It doesn't match the array type (at best it could match the internal raw array in a std::array, but the language rules don't support that).

Instead you can just use a raw array, to wit:

#include <stddef.h>
#include <array>

template<size_t N>
int b(int q, int const (&types)[N] )
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

int main()
{
    b( 9, { 2, 3 } );
}

Or, if you don't absolutely need N at compile time, you can use a std::initializer_list.

There are also many other possibly relevant approaches (e.g. variadic template function, or defining an operator to build up a std::vector), but it's difficult to say what would suit your undisclosed purpose.

like image 32
Cheers and hth. - Alf Avatar answered Sep 21 '22 18:09

Cheers and hth. - Alf