首页 > 解决方案 > C++模板推演——T变成指针类型

问题描述

我有这个代码片段

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

int main()
{
  int* i = new int(5);
  p(i);
}

1)根据https://cppinsights.io/模板功能相当于

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

/* First instantiated from: insights.cpp:18 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int *>(int *const & value)
{
  std::cout.operator<<(value).operator<<(std::endl);
}
#endif 

对我来说,这很奇怪。根据“有效现代 c++ 的第 1 项”,唯一可以将 T 推导出为 T&(或 T* 我猜)的情况是函数参数是通用引用(转发引用)。然而,这种情况 T 被推导出为 int*,但参数如果只是一个指针。

2)如果我更换

int* i = new int(5);

const int* i = new int(5);

这就是结果(我最初的预期)

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

/* First instantiated from: insights.cpp:18 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int>(const int * value)
{
  std::cout.operator<<(*value).operator<<(std::endl);
}
#endif


template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

3)回到1),如果我删除过载

template <typename T>
void p(const T& value)

所以我只有

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

int main()
{
  int* i = new int(5);
  p(i);
}

结果是

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int>(const int * value)
{
  std::cout.operator<<(*value).operator<<(std::endl);
}
#endif


int main()
{
  int * i = new int{5};
  p(i);
}

您能否解释一下为什么 T 在问题 1) 中可以推断为 int*) int 在问题 2) 中?另外我不明白模板参数推导的顺序 3)。

感谢您的任何提示/解释。

标签: c++template-argument-deduction

解决方案


从 to 的隐式转换序列优于从to的隐式转换int *序列。int * const &int *const int *

后者包含一个限定转换,而前者不包含。

模板参数推导是回答“我用什么类型代替T”的问题,而不是“什么是类型value”的问题。为此template <typename T> void p(const T* value)必须去掉参数的*类型。


推荐阅读