使用std :: array <type的实例,n =“”>作为模板参数

时间:2018-03-27 14:46:33

标签: c++ c++11 templates

我试图创建某种比较函数,将比较编译时已知的某些前缀到其他缓冲区。

我尝试使用包含前缀作为模板参数的预定义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;
} 

这些尝试是在阅读了以下似乎相关的答案后做出的:12

我有兴趣了解代码中的错误,就像找到有效的解决方案一样:)

Here是对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 个答案:

答案 0 :(得分:4)

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

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

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

您的代码:

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>在那里会变得不健全。我怀疑编译器是否被要求立即诊断此错误,因为SizeOfHeader的{​​{1}}参数使array的类型依赖。

答案 1 :(得分:2)

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

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

有关基本情况的详细信息,请参阅variadic function template without formal parameters

答案 2 :(得分:1)

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

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

以下是一个带有constexpr函数的完整C ++ 11工作示例,给定了几个相同类型和维度的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 , "!" );
 }