In C++ sizeof
有点独特,因为这样写是合法的:
int x;
sizeof(x); // a variable
也简单地说:
sizeof(int); // a type
(不过,我现在宁愿忽略第三个更奇怪的变体,不需要括号,因为我很确定这是不可能模仿的)
我希望自己能够复制这种行为。为了激励它,我有一个例子bitsof
操作员。
#include <climits>
template <typename T>
struct bits_traits {
enum { value = sizeof(T) * CHAR_BIT };
};
struct int_12_bit {
enum { bits = 12 };
// Let's pretent this has a bunch of code for looking and feeling like a 12bit int in a helpful and portable way
};
template <>
struct bits_traits<int_12_bit> {
enum { value = int_12_bit::bits };
};
#define bitsof(x) bits_traits<x>::value
int main() {
using std::size_t;
size_t b = bitsof(int);
size_t a = bitsof(int_12_bit);
int_12_bit x;
size_t c = bitsof(x); // <-- Not cool
}
显然,我可以使用 sizeof 以宏的形式编写整个内容,例如
#define bitsof(x) (sizeof(x) * CHAR_BIT)
但后来我就失去了“专业化”它的能力。
同样我可以写size_t c = bitsof(decltype(x))
。然而,我在这里要求的是一种在我自己的代码中模拟该行为的方法,而不必解决解决方法。我怎样才能写一个bitsof
看起来和感觉起来都像sizeof
,但是像特质一样专业?我必须接受吗sizeof
是不是有点特别并忍受它?
我最初有一些想法:
- Perhaps
decltype
作品就像sizeof
, e.g. decltype(0)
and decltype(int)
是同义的。但那里没有运气。
- 也许我们可以用指针/引用模板参数做一些事情。不过,我看不到一种方法可以让推论在这种情况下正常工作,并且这会对我们可以使用哪些变量施加额外的限制
bitsof
with.
- 也许是一些疯狂的 SFINAE 结合了模板和宏,但我看不到实现这种情况的方法,它总是只是一个语法错误。
- 可能可以使用 GCC 的语句表达式扩展来解决上述问题之一的局限性。
因为有一个简单的解决方法decltype
更多的是一个学习实验,我愿意接受使用任何 C++ 发布的编译器中可用的任何东西来针对任何过去、现在或未来标准的想法。
你可以这样做:
#include <type_traits>
#define bitsof(k) decltype(bitsof_left+(k)+bitsof_right)
template <class K>
struct bits_traits { /* whatever you want here */ };
struct bitsof_left_t {
template <class T>
bits_traits<T> operator+(const T&);
} bitsof_left;
struct bitsof_right_t {
template <class T>
friend T operator+(const T&, bitsof_right_t);
bitsof_right_t operator+();
template <class T>
operator T() const;
} bitsof_right;
int main()
{
using foo = bitsof(42);
using bar = bitsof(int);
static_assert(std::is_same<foo, bits_traits<int>>::value);
static_assert(std::is_same<bar, bits_traits<int>>::value);
}
它的工作原理是这样的。
a + (42) + b
被解析为(a + (42)) + b)
,然后重载二进制文件operator+
在我的示例中,运算符仅被声明,未定义,但由于它是未评估的上下文,因此并不重要。
a + (int) + b
被解析为a + ((int) (+ b))
。这里我们在右侧使用重载的一元 +,然后在左侧使用重载的强制转换运算符,然后在左侧使用重载的二进制 +。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)