const联盟成员的用途是什么?他们不是没有意义吗?

时间:2014-01-03 14:22:49

标签: c++ unions

在对answer的评论中,Koushik提出了very valid point

采取以下措施:

union U
{
    int x;
    const T y;
};

(我选择T,这样在这里没有共同的布局兼容性初始序列,这意味着每个[C++11: 9.5/1]在任何给定时间只有一个成员可能处于活动状态。)

由于任何时候只有一个成员可能处于“活动状态”(通过写入来激活),并且在初始化后无法写入y,这不是没有意义吗?我的意思是,y只能在第一次写入x时读取,并且仅在y是初始化成员时才会读取。

是否有一些用例我不见了?或者这确实是一种非常无意义的语言特征融合?

This has been mentioned before)功能

4 个答案:

答案 0 :(得分:2)

确实有用:

1)提供类似const_cast的技术。从某种意义上说,x = const_cast<...>(y)

2)处理模板时,有时您需要const版本的数据类型,以便匹配其他参数类型。

(我已经看到(1)在针对传统接口进行编程时使用。)

答案 1 :(得分:2)

不使用工会很多,但这可能是这样的情况:

#include <iostream>

class Accessor;
union Union
{
    private:
    friend class Accessor;
    int write;

    public:
    const int read;

    Union() : read(0) {}
};

class Accessor  {
    public:
    static void apply(Union& u, int i) { u.write = i; }
};

int main() {
    Union u;
    // error: ‘int Union::write’ is private
    // u.write = 1;
    std::cout << u.read << '\n';
    Accessor::apply(u, 1);
    std::cout << u.read << '\n';
}

注意:来自9.5联盟

  

注意:为了简化使用,我们提供了一项特殊保证   联合:如果标准布局联合包含多个标准布局   共享一个公共初始序列(9.2)的结构,以及一个对象   此标准布局联合类型包含标准布局之一   结构,允许检查任何共同的初始序列   标准布局结构成员;见9.2。 - 结束说明]

答案 2 :(得分:2)

这是一个参考语义类型的设计示例,您只需要授予const访问权限。 union用于从“类型擦除”函数返回的类似变体的数据类型。

#include <memory>

template<class T>
struct reference_semantics
{
public:
    reference_semantics(T* p ) : m(p) {}

    int observe() const { return *m; }
    void change(T p) { *m = p; }

private:
    T* m;
};

struct variant
{
    enum T { INT, DOUBLE } type;

    union U
    {
        reference_semantics<int> const i;
        reference_semantics<double> const d;

        U(int* p) : i(p) {}
        U(double* p) : d(p) {}
    } u;
};

#include <iostream>
std::ostream& operator<<(std::ostream& o, variant const& v)
{
    switch(v.type)
    {
        case variant::INT:
            return o << "INT: "<<v.u.i.observe();
        case variant::DOUBLE:
            return o << "DOUBLE: "<<v.u.d.observe();
    }
}

#include <string>

variant type_erased_access(std::string name)
{
    // imagine accesses to a map or so

    static double dval = 42.21;
    static int ival = 1729;

    if(name == "Lightness") return { variant::DOUBLE, &dval };
    else return { variant::INT, &ival };
}

int main()
{
    variant v0( type_erased_access("Lightness") );
    std::cout << v0 << "\n";
    variant v1( type_erased_access("Darkness") );
    std::cout << v1 << "\n";
}

现在想象一下,使用更大的数据类型而不是intdouble,而reference_semantics数据类型实际上提供的功能不仅仅是返回值。

甚至可能希望为某些参数返回reference_semantics<some_type> const,而为其他参数返回普通int。在这种情况下,您的union甚至可能包含const和非const成员。

答案 3 :(得分:-1)

如果联合表示某些方法/算法的结果的一部分,那么它可能是有意义的。但在这种情况下,我会同时制作两个值const

union T
{
    const int x;
    const int y;
};