整数类型的模板专业化如何工作?

Pas*_*sha 6 c++ templates template-specialization c++11

我有一个带有单个参数的模板函数<T>,我想对不同的整数类型进行此函数的特化.起初这似乎很明显,但经过几次尝试后我发现我并不真正理解专业化在这里是如何工作的,以及如何实现某种程度的可移植性......

这是测试程序:

// clang test.cc -std=c++11 -lc++
#include <iostream>
#include <typeinfo>

template <typename T> void foo()  { std::cout << "  foo<T> with T=" << typeid(T).name() << '\n'; }
template <> void foo<int>()       { std::cout << "  foo<int>\n"; }
template <> void foo<long>()      { std::cout << "  foo<long>\n"; }
template <> void foo<long long>() { std::cout << "  foo<long long>\n"; }
template <> void foo<size_t>()    { std::cout << "  foo<size_t>\n"; }
// template <> void foo<int64_t>()  { std::cout << "  foo<int64_t>\n"; } // error


int main () {
  std::cout << "sizeof(int)=" << sizeof(int) << ", ";
  std::cout << "sizeof(long)=" << sizeof(long) << ", ";
  std::cout << "sizeof(long long)=" << sizeof(long long) << ", ";
  std::cout << "sizeof(size_t)=" << sizeof(size_t) << "\n";
  foo<int>();
  foo<long>();
  foo<long long>();
  foo<size_t>();
  foo<ssize_t>();
  foo<int8_t>();
  foo<int16_t>();
  foo<int32_t>();
  foo<int64_t>();
  foo<uint32_t>();
  foo<uint64_t>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它在我的机器上产生

sizeof(int)=4, sizeof(long)=8, sizeof(long long)=8, sizeof(size_t)=8
  foo<int>
  foo<long>
  foo<long long>
  foo<size_t>
  foo<long>
  foo<T> with T=a
  foo<T> with T=s
  foo<int>
  foo<long long>
  foo<T> with T=j
  foo<T> with T=y
Run Code Online (Sandbox Code Playgroud)

所以这就是我不明白的地方:

  1. 如果longlong long是相同的类型,为什么编译器允许两个特化共存?
  2. 为什么添加专门化int64_t会产生错误?
  3. 为什么foo<int64_t>作为解决foo<long long>foo<long>
  4. 为什么foo<ssize_t>作为解决foo<long>foo<long long>
  5. 为什么foo<uint64_t>不使用专业化foo<size_t>
  6. 我在这里观察到的行为是通用的还是机器特定的?我怎么能确定这段代码是可移植的?

max*_*x66 5

1)如果longlong long是同一类型,为什么编译器允许两种特化共存?

因为longlong long可以在相同的低级类型上实现,但从语言的角度来看,是不同的基本类型。

2)为什么添加专门化会int64_t产生错误?

因为std::int64_t不是算术基本类型,而是另一种类型的别名(通过typedefor定义using

3)为什么foo<int64_t>解析为foo<long long>和不是foo<long>

因为,在您的平台中,std::int64_t被定义为 的别名long long,而不是 for long(或别名的别名...);所以,在你的平台上,std::int64_tlong long;在不同的平台,可能会有不同的结果

4)为什么foo<ssize_t>解析为foo<long>和不是foo<long long>

与 相同std::int64_t:类型ssize_t(不是标准类型)是 的别名(在您的平台中)long,而不是long long

5)为什么foo<uint64_t>不使用专业化foo<size_t>

因为std::uint64_tstd::size_t不是基本算术类型,但两者都是其他类型的别名(我想是unsigned longunsigned long long),并且在您的平台中,它们是不同类型的别名

6)我在这里观察到的行为是普遍的还是特定于机器的?我如何确定该代码是可移植的?

除了第 (1) 点(这是永远正确的,因为long和之间的差异long long是语言的一部分)之外,它在很大程度上依赖于平台。

但可以使用示例std::is_same和其他类型特征来管理它。