【问题标题】:Why is template<classTp> bool is_array<Tp[]> a partial specialization for template<class T> bool is_array<Tp>?为什么 template<classTp> bool is_array<Tp[]> 是 template<class T> bool is_array<Tp> 的部分特化?
【发布时间】:2021-01-03 08:27:45
【问题描述】:

如何理解template&lt;typename Tp&gt; bool is_array&lt;Tp[]&gt; = truetemplate&lt;typename T&gt; bool is_array&lt;Tp&gt; = true 的部分特化?

这里是相关的code snippet:

#include<iostream>

template<typename T>
bool is_array = false;

template<typename Tp>
bool is_array<Tp[]> = true;

int main()
{
    std::cout << is_array<int> << std::endl;
    std::cout << is_array<int[]> << std::endl;
}

我也注意到,一般来说,部分模板特化中的模板参数数量少于主模板中的模板参数数量。

部分专业化通常被视为this

#include<iostream>

template<typename T, typename U>
class add
{
public:
    add(T x, U y)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};

template<typename U>
class add<int, U>
{
    public:
    add(int x, U y)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;       
    }
};

int main()
{
    add<int, double>(1, 5.0);
    add<char, int>('a', 9);
}

【问题讨论】:

  • TTp[] 的图像,如T = int[]
  • 我不确定你到底在问什么。你不清楚部分模板特化的规则吗?
  • @cigien 我有理由肯定约翰问为什么数组版本被认为是专业化的,即不选择 is_array = false;
  • @CaptainGiraffe 是的,对不起我的英语不好。我的问题是为什么数组版本被认为是专业化的。而且一般来说,部分模板特化中的模板参数的数量少于主要的。
  • 我已经扩展了我的答案以解决有关模板参数数量的部分。

标签: c++ templates template-specialization


【解决方案1】:

要使模板成为primary专业化,它需要比主要模板更加专业化。这基本上意味着特化必须匹配主要类型可以匹配的严格子集

在您的情况下,专业化将匹配 int[]char[] 等。主要也将匹配这些类型,但主要还会匹配 intcharstd::vector&lt;std::string&gt; 等类型。

当指定像is_array&lt;int[]&gt; 这样的模板参数时,规则说首先尝试特化。在这种情况下,Tp[] 可以匹配到int[](基本上是用int 代替Tp),因此选择了专业化。

当指定像 is_array&lt;int&gt; 这样的模板参数时,首先尝试特化,但匹配失败。然后尝试主模板,并且匹配,因此选择了主模板。

正如您所提到的,专业化通常具有较少的模板参数。这不是必需的,只要我上面提到的规则适用,即特化必须匹配主要可以匹配的类型的严格子集。

事实上,特化甚至可以比主要拥有更多的模板参数。同样,要求只是特化匹配主要匹配类型的子集。

【讨论】:

【解决方案2】:

这是编译器为您的代码生成的中间输出(参考 cppinsights

编译器正在使用数组的专用模板。

template<typename T>
bool is_array = false;

template<>
bool is_array<int> = false;
template<>
bool is_array<int []> = true;

template<typename Tp>
bool is_array<Tp[]> = true;

int main()
{
  std::cout.operator<<(is_array<int>).operator<<(std::endl);
  std::cout.operator<<(is_array<int []>).operator<<(std::endl);
}

现在如果删除下面的代码

template<typename Tp>
bool is_array<Tp[]> = true;

编译器会生成

template<typename T>
bool is_array = false;

template<>
bool is_array<int> = false;
template<>
bool is_array<int []> = false;

int main()
{
  std::cout.operator<<(is_array<int>).operator<<(std::endl);
  std::cout.operator<<(is_array<int []>).operator<<(std::endl);
}

您可以看到编译器只是将T 替换为int[],这只是您提供的第二个模板,一个专门的模板。

【讨论】:

  • 我认为第一个代码 sn-p 中没有部分专业化(在您的答案中)。这确实是一个完整的专业化。
【解决方案3】:

专业化甚至可以有比主要的更多的模板参数。这是example

#include<iostream>

template<typename T>
bool is_array = false;
    
template <typename Tp, int N>
bool is_array<Tp[N]> = true;

int main()
{
    std::cout << is_array<int> << std::endl;
    std::cout << is_array<int[5]> << std::endl;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多