我想为C ++中的原始类型创建一个包装类,以便为它重载函数和运算符。但是,否则我希望它的行为与原始类型完全相同。例如,我希望它是POD类型,因此它可以用在(单独编译的)C代码访问的结构中,并且可以隐式地转换为原始类型。作为一个具体的例子,我想要类似Boost tribool的东西,但这是一个保证sizeof为1的POD。C ++ 03兼容性是非常可取的,但是仅C ++ 11可能也是有用的。

像这样的入门很容易:

struct tribool_pod {
    unsigned char value; // can be private in C++11
    tribool_pod& operator=(unsigned char v) { value = v; return *this; }
    constexpr operator unsigned char() const { return value; }
    tribool_pod& operator=(bool v) { value = v ? 1 : 0; return *this; }
    constexpr operator bool() const { return value == 1; }
};


请注意,没有用户定义的构造函数,因此到目前为止,它是POD类型。但是,在编写运算符时遇到了第一个障碍:

constexpr tribool_pod operator!() const {
    return value == 0 ? <true-value> :
           value == 1 ? <false-value> :
           <indeterminate-value>;
}


在这种情况下,在诸如<true-value>之类的表达式中创建实例的最佳方法是什么?在C ++ 11中,我可以使用tribool_pod{true},但是在C ++ 03中有什么方法吗?如果C ++ 03中的结构只能在变量声明中进行初始化,那么我想为诸如<true-value>之类的东西编写常量表达式的唯一方法就是引用static const tribool_pod(具有外部链接)。这样做的缺点是不能仅使用标头,而且效率可能比使用原始类型低。

即使在C ++ 11中,一个相关的问题是我没有从booltribool_pod的转换。显然,如果我将转换构造函数添加到tribool_pod,则它不再是POD。

我是否缺少某些技巧,或者这根本上是不可能的?这似乎是C ++构造函数成为全有或全无命题的不幸结果:构造函数是唯一的隐式转换函数,但是如果定义了任何转换函数,则始终会调用它,并且您不再是POD类型。 (或者用C ++ 11而言,它具有标准布局,但并不琐碎(可构造))。

还是我太担心POD风格?如果我包括转换构造函数和无操作默认构造函数,那我会失去什么呢?只是像goto这样的超级晦涩难懂的初始化对象?我认为我可以使用来自实际编译器的C ++ 03来假设标准布局(例如,在对象的开头没有填充),即使规范不能保证这样做。

注意:我关心这个问题的部分原因是因为我希望从C使用相同的标头(功能和安全性下降)。例如:

#ifdef __cplusplus
struct tribool_pod { unsigned char value; ... };
#else
typedef unsigned char tribool_pod;
#endif

最佳答案

使用块静态特殊值的仅标头解决方案:

Foo Foo::f()
{
    static const Foo special = make_special_foo();   // or "= { 1, 2, 3 };" etc.

    return condition ? value : special;
}

关于c++ - 在C++中既可以POD又可以在表达式中构造的原始类型包装器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19988908/

10-16 11:44