【发布时间】:2018-02-15 19:27:41
【问题描述】:
我有一个带有单个参数<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;
}
它在我的机器上产生
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
这就是我不明白的地方:
- 如果
long和long long是同一类型,为什么编译器允许这两种特化共存? - 为什么为
int64_t添加专业化会产生错误? - 为什么
foo<int64_t>解析为foo<long long>而不是foo<long>? - 为什么
foo<ssize_t>解析为foo<long>而不是foo<long long>? - 为什么
foo<uint64_t>不使用特化@987654334@? - 我在这里观察到的行为是通用的还是特定于机器的?如何确定此代码是可移植的?
【问题讨论】:
-
int64_t和ssize_t等类型只是long或unsigned long等内置类型的别名。与其他一些语言不同,C++ 不提供任何声明“强”类型别名的方法,因此针对同一底层类型的不同别名的模板特化总是会导致错误。 -
#1 是您的错误假设。 “相同大小”并不意味着“相同类型”。就像
char是signed char和unsigned char的不同类型一样,尽管它的行为与其中一个相同。 -
'long' 和 'long long' 与您的编译器的 size 相同,但它们的 type 不同。
-
@Pete Becker 并且,取决于平台/编译器,可能不会总是是相同的大小。
标签: c++ c++11 templates template-specialization