我想实现一个处理所有简单C ++类型的函数(也是STL容器和更多类型,但它们不会让我头疼),通用函数处理所有其他类型,如下所示:
template <typename T>
void dostuff(T& arg)
{ cout << "generic version" << endl; }
void dostuff(int& arg)
{ cout << "something useful" << endl; }
void dostuff(unsigned int& arg)
{ cout << "something slightly different" << endl; }
void dostuff(short& arg)
{ cout << "something slightly different again" << endl; }
// ...and so on for all integer types...
这里我将自己限制为整数类型,因为它们会造成所有麻烦。当然,如果我为同一类型实现两次函数,编译器会抱怨。混合unsigned int
和std::size_t
等内容时会发生这种情况。它适用于我的系统,但不能在32位平台上编译。我理解这个问题,但我不知道如何实现便携式解决方案。
我认为最系统的方法是使用std :: int8_t(std :: uint8_t,16,32,64)类型系列,因为它们不会重叠并且旨在覆盖可用范围。事实证明,这还不够,如以下代码所示:
#include <type_traits>
#include <cstdint>
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << "SIZE:" << endl;
cout << "sizeof(unsigned long) = " << sizeof(unsigned long) << endl;
cout << "sizeof(unsigned long long) = " << sizeof(unsigned long long) << endl;
cout << "sizeof(std::size_t) = " << sizeof(std::size_t) << endl;
cout << "sizeof(std::uint64_t) = " << sizeof(std::uint64_t) << endl;
cout << endl;
cout << "SIGNED?" << std::boolalpha << endl;
cout << std::is_signed<unsigned long>::value << endl;
cout << std::is_signed<unsigned long long>::value << endl;
cout << std::is_signed<std::size_t>::value << endl;
cout << std::is_signed<std::uint64_t>::value << endl;
cout << endl;
cout << "SAME?" << endl;
cout << std::is_same<unsigned long, unsigned long long>::value << endl;
cout << std::is_same<unsigned long, std::size_t>::value << endl;
cout << std::is_same<unsigned long, std::uint64_t>::value << endl;
cout << std::is_same<unsigned long long, std::size_t>::value << endl;
cout << std::is_same<unsigned long long, std::uint64_t>::value << endl;
cout << std::is_same<std::size_t, std::uint64_t>::value << endl;
}
在我的带有clang 3.8的64位MacOS系统上,它提供了以下输出:
SIZE:
sizeof(unsigned long) = 8
sizeof(unsigned long long) = 8
sizeof(std::size_t) = 8
sizeof(std::uint64_t) = 8
SIGNED?
false
false
false
false
SAME?
false
true
false
false
true
false
所以我有四个64位无符号整数类型,但它们实际上只指两个不同的类型。还有更多候选人,例如std::uintptr_t
,std::ptrdiff_t
和std::uint_fast64_t
,我甚至不知道该列表是否完整。
对于我来说,哪些类型相同的定义看起来是任意的,但我发现,对于我所面临的确切问题,我们希望将long
和long long
视为不同。
问题:有没有办法为不同整数类型的详尽列表实现上述功能,这样我就不会在不同的平台上遇到麻烦?如果是这样,这个清单是什么?如果不是,那么实现所需行为的最佳方法是什么(处理所有整数类型,未知类型的有意义的默认行为,便携式解决方案)?
答案 0 :(得分:3)
由于您尝试针对每种特定的整数类型执行不同的操作,即使您可以枚举程序中的所有类型,也无法构成特定的特殊逻辑。
相反,我要建议的是根据需要实现说short
,int
,unsigned
等的特殊逻辑,并设置一个静态断言{{1在您的主模板中是is_integral<T>
,并显示一条消息,表明它是使用不支持的整数类型调用的,需要确定和编写自定义逻辑。
答案 1 :(得分:2)
专注于所有整数类型通常是一个非常糟糕的主意。根据评论中的讨论,我假设静态调度的大小&amp;类型的签名适合你。以下是如何做到的:
#include <iostream>
#include <type_traits>
template <typename T, unsigned Size, bool Signed>
struct foo_impl;
template <typename T>
struct foo_impl<T, 1, false>
{
static void foo (T & x) { std::cout << x << " is unsigned 8-bit" << std::endl; }
};
template <typename T>
struct foo_impl<T, 1, true>
{
static void foo (T & x) { std::cout << x << " is signed 8-bit" << std::endl; }
};
template <typename T>
struct foo_impl<T, 2, false>
{
static void foo (T & x) { std::cout << x << " is unsigned 16-bit" << std::endl; }
};
// more specializations ...
template <typename T>
void foo (T & x)
{
// dispatch based on size & signedness
foo_impl<T, sizeof(T), std::is_signed<T>::value>::foo(x);
}
int main ( )
{
char a = 5;
std::uint8_t b = 6;
unsigned short c = 7;
foo(a);
foo(b);
foo(c);
}