Union members may not have constructors, but is `std :: pair` ok?

The members

unionmay not have destructors or constructors. Therefore, I cannot create the following class Foomyself MyClassif it MyClasshas a constructor:

template<class T>
struct Foo {
  T val;
  Foo(T val_) : val(val_) {}
  size_t hash() const {
    union {T f; size_t s;} u = { val };
    return u.s;
  }
};
struct MyClass {
  bool a;
  double b;
  MyClass(bool a_, double b_) : a(a_), b(b_) {}
};

If I do this, I will get this error:

member 'MyClass Foo<T>::hash() const 
[with T = MyClass]::<anonymous union>::f' with constructor 
not allowed in union

To get around this, I created MyClasswith an inconvenient constructive function that first copies the thing:

struct MyClass {
  bool a;
  double b;
};
MyClass createMyClass(bool a, double b) {
  MyClass m;
  m.a = a;
  m.b = b;
  return m;
}

But I am wondering if there is a better way than using this feature createMyClass. The constructor will be more effective, and as soon as a critical component MyClass, and Foo<MyClass>will be designed in a million times in my code.

stand :: Pair

I am also a little surprised what can be used std::pairin union:

Foo<std::pair<bool, double> > f2(std::make_pair(true, 3.12));

, std::pair (. ) ?

+5
4

EDIT: std::pair , . , 9.5.1. : 12.1.5:

X, . inline public . :

  • ,
  • ,
  • , ( ),

20.2.2.2 , :

pair(const T1& x, const T2& y);

, .

, (Visual Studio 2008), , std::pair. std::pair foo, :)

namespace foo {
    template<class _Ty1, class _Ty2> struct pair {
        typedef _Ty1 first_type;
        typedef _Ty2 second_type;
        pair() : first(_Ty1()), second(_Ty2()) {
        }
    }
}

//This doesn't work in VC2008
union Baz {
    foo::pair<bool, double> a;
    int b;
}
//This works in VC2008
union Buz {
    std::pair<bool, double> a;
    int b;
}

. C (short for construct), , CMyClass(a, b).

, -. -, ( , , , ), f s , -, , , min(sizeof(s), sizeof(f)) , MyClass . bool a, :

  • int bool, - : true false.
  • char bool. , , sizeof(int), , , 1. , MyClass , , - .

T, , , , - .

+10

:

size_t hash() const {
    union {T f; size_t s;} u = { val };
    return u.s;
}

:

size_t hash() const {
    size_t s = 0;
    memcpy(&s, &val, std::min(sizeof(size_t), sizeof(T)));
    return s;
}

, , memcpy , . , , , T .

-, T - . MyClass , bool size_t , double , .

, . T , , , , : vtable...

+4

std::pair , , . (§12.1):

( ), .

, , . std::pair (§20.2.2) , . , , .

N.B.: , , :

"ComeauTest.c", line 8: error: invalid union member -- class
          "std::pair<bool, double>" has a disallowed member function
      union {T f; size_t s;} u = { val };
               ^
          detected during instantiation of "unsigned int Foo<T>::hash() const
                    [with T=std::pair<bool, double>]" at line 22
+2

: ?

, , . , :

size_t hash() const {
  return reinterpret_cast<size_t>(val);
}

which should perform the same trick (I think) with greater efficiency, since no object is allocated on the stack by size sizeof(T).

+2
source

All Articles