开发者问题收集

使用 std::array<Type, N> 的实例作为模板参数

2018-03-27
167

我正在尝试创建某种比较函数,将编译时已知的某些前缀与其他缓冲区进行比较。

我正在尝试使用将前缀作为模板参数保存的预定义 std::array

这是我尝试过的:

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;
} 

这些尝试是在阅读以下看似相关的答案后做出的: 1 2

我对理解代码中的错误和找到可行的解决方案都很感兴趣:)

这里 是 coliru 的失败尝试。错误如下:

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.
3个回答

不能将类类型的实例作为模板非类型参数传递。

您可以将引用和指针传递给类类型,但不能传递实例本身。

关于在未来的标准修订版中允许这样做( 之后)已经有一些讨论。

您的代码:

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

这需要一个模板模板参数,而不是该模板参数的实例。

template<class, class>
class bob;

模板 bob (不是它的类实例,也不是它的类实例的值实例)是 foo2 的有效第一个模板参数。

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

这不是有效的模板声明。 std::array<std::uint8_t, SizeOfHeader> 在此处将出现格式错误。我怀疑编译器是否被要求立即诊断此错误,因为 arraySizeOfHeader 参数使 array 的类型相关。

Yakk - Adam Nevraumont
2018-03-27

您可以使用可变参数模板直接传递参数,即:

#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...>();
}

有关基本情况的详细信息,请参阅 没有形式参数的可变函数模板

Acorn
2018-03-27

另一种方法是使用 constexpr 函数,如果您想要强制执行编译时,您可以使用它(通过示例)初始化 constexpr 值。

不幸的是,您标记了 C++11,因此 constexpr 函数不太灵活。

以下是一个完整的 C++11 工作示例,其中包含一个 constexpr 函数,给定几个相同类型和维度的 std::array ,返回相应相等元素的数量。该值在 constexpr val 变量中注册,此外,使用 static_assert

#include <array>
#include <cstdint>

template <typename T, std::size_t N>
constexpr std::size_t countEqual (std::array<T, N> const & a1,
                                  std::array<T, N> const & a2,
                                  std::size_t pos = 0U,
                                  std::size_t count = 0U)
 {
   return pos < N ? countEqual(a1, a2, pos+1U,
                               a1[pos] == a2[pos] ? ++count : count)
                  : count;
 }

int main (void)
 {
   constexpr std::array<std::uint8_t, 4> ARRAY_A {{0xDE, 0xAD, 0xBE, 0xEF}};
   constexpr std::array<std::uint8_t, 4> ARRAY_B {{0xBA, 0xAD, 0xF0, 0x0D}};

   constexpr auto val { countEqual(ARRAY_A, ARRAY_B) };

   static_assert( val == 1U , "!" );
 }
max66
2018-03-27