Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an instance of an std::array<Type, N> as a template parameter

I'm trying to create some sort of comparison function that will compare certain prefixes that are known at compile time to other buffers.

I'm trying to use the predefined std::arrays that hold the prefixes as template parameters.

Here is what I tried:

constexpr std::array<std::uint8_t, 4> ARRAY_A {{0xDE, 0xAD, 0xBE, 0xEF}};
constexpr std::array<std::uint8_t, 4> ARRAY_B {{0xBA, 0xD, 0xF0, 0x0D}};

enum class Foo{
    A,B

    };

template<size_t SizeOfHeader, std::array<std::uint8_t, SizeOfHeader> Header, Foo f> 
void foo()
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

template<template<class, class> class TContainer, Foo f> 
void foo2()
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}


int main()
{
    foo2<ARRAY_A, Foo::A>();
    foo<ARRAY_A.size(), ARRAY_A, Foo::A>();
    return 0;
} 

These attempts were made after reading the following answers which seemed related: 1 , 2.

I'm interested in understanding the errors in the code as much as finding a working solution :)

Here is the failed attempt at coliru. The errors are:

main.cpp:31:5: error: no matching function for call to 'foo2'
    foo2<ARRAY_A, Foo::A>();
    ^~~~~~~~~~~~~~~~~~~~~
main.cpp:23:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'TContainer'
void foo2()
     ^
main.cpp:32:5: error: no matching function for call to 'foo'
    foo<ARRAY_A.size(), ARRAY_A, Foo::A>();
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:17:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Header'
void foo()
     ^
2 errors generated.
like image 483
Dlavimer Tupin Avatar asked Nov 26 '25 12:11

Dlavimer Tupin


2 Answers

You cannot pass instances of class types as template non-type parameters.

You can pass references and pointers to class types, but not instances themselves.

There has been some discussion about permitting this in a future standard revision (after c++17).

Your code:

template<template<class, class> class TContainer, Foo f> 
void foo2()

this takes a template template parameter, not an instance of that.

template<class, class>
class bob;

the template bob (not a class instance of it, or a value instance of a class instance of it) is a valid first template argument for foo2.

template<size_t SizeOfHeader, std::array<std::uint8_t, SizeOfHeader> Header, Foo f> 
void foo()

this is not a valid template declaration. std::array<std::uint8_t, SizeOfHeader> is going to be ill-formed there. I doubt the compiler is mandated to diagnose this error immediately, because SizeOfHeader argument to array makes the type of array dependent.

like image 76
Yakk - Adam Nevraumont Avatar answered Nov 28 '25 02:11

Yakk - Adam Nevraumont


You could pass directly the parameters using a variadic template, i.e.:

#include <type_traits>

template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == 0>::type f()
{
}

template<std::uint8_t a, std::uint8_t... rest>
void f()
{
    f<rest...>();
}

See variadic function template without formal parameters for details about the base case.

like image 28
Acorn Avatar answered Nov 28 '25 02:11

Acorn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!