我有一个模板函数,它只有一个参数<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>
为什么不使用特化foo<size_t>
?- 我观察到的行为是通用的还是机器特定的?我如何确保此代码可移植性?
int64_t
和ssize_t
之类的类型只是内置类型long
或unsigned long
的别名。与其他一些语言不同,C++ 不提供任何声明“强”类型别名的方法,因此针对相同基础类型的不同别名的模板特化将始终导致错误。 - user7860670char
对于signed char
和unsigned char
来说是一个独立的类型,尽管它的行为与其中一个完全相同。 - StoryTeller - Unslander Monica