【问题标题】:Using an instance of an std::array<Type, N> as a template parameter使用 std::array<Type, N> 的实例作为模板参数
【发布时间】:2018-03-27 14:46:33
【问题描述】:

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

我正在尝试使用预定义的std::arrays,它将前缀作为模板参数。

这是我尝试过的:

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.

【问题讨论】:

  • @Quentin 包含完整错误和演示链接
  • 完美! ------

标签: c++ c++11 templates


【解决方案1】:

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

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

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

您的代码:

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&lt;std::uint8_t, SizeOfHeader&gt; 将在那里不正确。我怀疑编译器是否必须立即诊断此错误,因为arraySizeOfHeader 参数使array 的类型依赖。

【讨论】:

  • 是否有规范部分禁止这样做,或者只是不允许这样做?我将如何发送参考,例如ARRAY_A ?
  • @DlavimerTupin 只是将参数类型作为参考。但是请注意,您只能将该参数绑定到具有外部链接的静态生命周期对象(即全局和静态成员)。
  • @Quentin 谢谢,如果没有参考const,它就不起作用了:)
【解决方案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

【讨论】:

    【解决方案3】:

    另一种方法是使用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 , "!" );
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-19
      • 2013-05-25
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      • 2023-03-10
      相关资源
      最近更新 更多