目前,我对代码从64(后退)到32位的可移植性有疑问。问题是,对于64位平台,类的方法已重载,而与32位平台上的另一重载冲突。
这两种方法如下:
void myfunc(unsigned o);
void myfunc(size_t o);
在32位体系结构上,它们看起来与编译器相同,并引发一些错误。
所以,问题是,是否可以做这样的事情:
void myfunc(unsigned o);
#if typeid(unsigned) != typeid(size_t)
void myfunc(size_t o);
#endif
我当前的解决方案如下:
void myfunc(unsigned o);
#if __WORDSIZE == 64
void myfunc(size_t o);
#endif
但是还有一些不好的感觉,即WORDSIZE不是最合适的,因为这并不一定意味着类型不相同。
编辑:好的,这是有问题的位置线705和706,它们在32位臂上编译时会产生错误。 https://github.com/ceph/ceph/blob/master/src/include/buffer.h#L705
答案 0 :(得分:3)
如果基础的C标准库支持"Floating-point extensions part 1" (ISO/IEC TS 18661-1:2014),则您具有可用的预处理器宏,可用于标识类型的大小:
#include<climits>
#include<cstdint>
void myfunc(unsigned o);
#if UINT_WIDTH != SIZE_WIDTH
void myfunc(size_t o);
#endif
例如,这受支持由glibc。请注意,如果未定义宏(即未实现规范),则测试总是会失败,因此您也应该检查一下,即
#if UINT_WIDTH != SIZE_WIDTH || !defined(UINT_WIDTH) || !defined(SIZE_WIDTH)
没有这样的实现定义的宏,由于预处理器实际上并不了解C或C ++类型,因此无法用于实现所需的功能。
任何在C ++编译级别的解决方案都将要求您至少在某种程度上修改函数声明。
我认为此解决方案不是特别干净,但是您当前的解决方案也不是。确实,如果我怀疑目标是避免某些隐式转换,则该方法应该是一个模板,其中static_assert
适当地限制了类型。
编辑:
上面的代码与当前的glibc和gcc一样工作,但是我不确定从技术上讲这是否正确。这是扩展C11而不是C ++的技术规范。我不知道C ++如何或是否合并了这些内容,或者它们是否将被视为实现定义的扩展。
还应根据规范仅在您定义了宏的情况下
#define __STDC_WANT_IEC_60559_BFP_EXT__
在第一个#include<stdint.h>
或#include<limits.h>
之前。在C模式下进行编译时,使用glibc的GCC实际上确实需要这样做。
是否可以通过比较宏__STDC_IEC_60559_BFP__
与201ymmL
来检查是否实现了规范。但是,带有glibc的GCC似乎没有设置此宏,并且文档指出对规范的支持只是部分的。
在信任上述比较之前,可能至少应确保已设置UINT_WIDTH
和SIZE_WIDTH
。如果不是,例如因为不支持该规范,所以它将始终评估为0 != 0
,即false
。
答案 1 :(得分:1)
这可能是使用模板的选项:
#include <iostream>
class A {
public:
template<typename T>
std::enable_if_t<std::is_same<T, int>::value ||
std::is_same<T, unsigned>::value ||
std::is_same<T, std::size_t>::value >
advance(T o) {
std::cout << "s" << std::endl;
A::advance<unsigned>(static_cast<unsigned>(o));
}
};
template<>
void A::advance(int o) = delete;
template<>
void A::advance(unsigned o) {
std::cout << "u" << std::endl;
}
int main()
{
A a;
unsigned x;
std::size_t y;
int z;
char p;
a.advance(x);
a.advance(y);
//a.advance(z);
//a.advance(p);
return 0;
}
答案 2 :(得分:0)
您可以使用std::enable_if
:
#include <type_traits>
struct S {
void advance(unsigned o);
std::enable_if<!std::is_same<unsigned, std::size_t>::value>::type
advance(std::size_t o) { advance(static_cast<unsigned>(o)); }
};
尽管,正如其他人已经指出的那样,我将放弃unsigned
变体,而仅保留std::size_t
变体。