以数组为参数的模板专业化

时间:2019-01-12 10:35:27

标签: c++ c++11 templates template-specialization

我正在尝试对此功能模板进行专门化:

template< typename T, std::size_t Size>
T Max(T(&pArr)[Size]) {
    T result{ *pArr };

    for (size_t i{ 1 }; i < Size; i++) {
        result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i];
    }
    return result;
}

我想专门针对const char *。我尝试了很多东西,但是其中任何一个都可以。当尝试这种方式时:

template<std::size_t SIZE>
const char* Max<const char*>(const char *(&pArr)[SIZE]) {
    char result{ *pArr };

    for (size_t i{ 1 }; i < SIZE; i++) {
        result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i];
    }
    return result;
}

我遇到错误:'Max':非法使用显式模板参数。 有人可以帮我吗?我想了解为什么它不起作用以及如何使其起作用。

谢谢!

2 个答案:

答案 0 :(得分:3)

您不能部分专业化功能。但是您不必这样做,因为函数已经支持重载。您只需为char创建一个重载。您的版本有两个错误。

  1. 您已将结果变量声明为const char*,但应为>
  2. 使用#include<cstring> template< typename T, std::size_t Size> T Max(T(&pArr)[Size]) { T result{ *pArr }; for (size_t i{ 1 }; i < Size; i++) { result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i]; } return result; } bool greater(const char* first, const char* second){ return strlen(first) > strlen(second); } template<std::size_t SIZE> const char* Max(const char *(&pArr)[SIZE]) { const char* result{ *pArr }; for (size_t i{ 1 }; i < SIZE; i++) { result = greater(pArr[i - 1],pArr[i]) ? pArr[i - 1] : pArr[i]; } return result; } int foo() { int ints[] = {1, 2}; return Max(ints); } const char* bar() { const char* stuff[] = {"1222", "234", "sfsdfsd"}; return Max(stuff); } 比较随机指针不会产生有意义的结果。您必须决定如何称呼一个比另一个大。

链接:https://gcc.godbolt.org/z/VKE4Jy


Max

答案 1 :(得分:0)

您的代码存在的问题是C ++ 11不支持模板函数的部分专业化。只有完整的专业化。

鉴于您的Max()函数,以下是可能的完全专业化

template <>
int Max<int, 4u>(int(&pArr)[4u])
 {
   int result{ *pArr };

   for (size_t i{ 1 }; i < 4u; i++) 
      result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i];

   return result;
 }

您可以绕开这些限制,在模板struct / class中插入一个函数,然后部分专门化struct / class。

例如,给定以下模板struct,其中包含static func()函数

template <typename T, std::size_t N>
struct MaxS
 {
   static T func (T (&a)[N])
    {
      T result{ a[0] };

      for (size_t i{ 1 }; i < N; i++)
         result = a[i - 1] > a[i] ? a[i - 1] : a[i];

      return result;
    }
 };

您可以对所有int C样式数组进行部分专业化处理,如下所示

template <std::size_t N>
struct MaxS<int, N>
 {
   static int func (int (&a)[N])
    {
      int result{ a[0] };

      for (size_t i{ 1 }; i < N; i++)
         result = a[i - 1] > a[i] ? a[i - 1] : a[i];

      return result;
    }
 };

不幸的是,这样一来,您就无法推断出类型和大小。因此,您明确要求他们按如下所述呼叫func()(例如)

MaxS<int, 4>::func(a)

以下是这两种解决方案的完整编译示例

#include <iostream>

template< typename T, std::size_t Size>
T Max(T(&pArr)[Size])
 {
   std::cout << "Max(), generic version" << std::endl;

   T result{ *pArr };

   for (size_t i{ 1 }; i < Size; i++)
      result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i];

   return result;
 }

template <>
int Max<int, 4u>(int(&pArr)[4u])
 {
   std::cout << "Max(), full specialization" << std::endl;

   int result{ *pArr };

   for (size_t i{ 1 }; i < 4u; i++) 
      result = pArr[i - 1] > pArr[i] ? pArr[i - 1] : pArr[i];

   return result;
 }

template <typename T, std::size_t N>
struct MaxS
 {
   static T func (T (&a)[N])
    {
      std::cout << "MaxS::func(), generic version" << std::endl;

      T result{ a[0] };

      for (size_t i{ 1 }; i < N; i++)
         result = a[i - 1] > a[i] ? a[i - 1] : a[i];

      return result;
    }
 };

template <std::size_t N>
struct MaxS<int, N>
 {
   static int func (int (&a)[N])
    {
      std::cout << "MaxS::func(), int partial specialization" << std::endl;

      int result{ a[0] };

      for (size_t i{ 1 }; i < N; i++)
         result = a[i - 1] > a[i] ? a[i - 1] : a[i];

      return result;
    }
 };


int main()
{
   int  a [] { 1, 2, 3, 4 };
   long b [] { 1, 2, 3, 4 };
   int  c [] { 1, 2, 3, 4, 5 };

   std::cout << Max(a) << std::endl;
   std::cout << Max(b) << std::endl;
   std::cout << Max(c) << std::endl;

   std::cout << MaxS<int, 4>::func(a) << std::endl;
   std::cout << MaxS<long, 4>::func(b) << std::endl;
   std::cout << MaxS<int, 5>::func(c) << std::endl;
}