c++visual-c++visual-c++-2015

Initialize an array member of class when class's copy constructor is deleted


Here is a smaller version of a use case that I am working on.

#include <mutex>
template<typename T = float>
class Foo
{
public:
    Foo(int x, int y):m_mutex(){}
private:
    std::mutex  m_mutex; // This is must have in my project
};

typedef Foo<float> Foo_typedef;

class Func
{
public:     
    static Foo_typedef static_array[2];
};

Foo_typedef Func::static_array[2] = { Foo_typedef(2,3), Foo_typedef(2,3) };

int main()
{   
    return 0;
}

After compiling this VS 2015 Update 2 emits following errors.

error C2280: 'Foo<float>::Foo(const Foo<float> &)': attempting to reference a deleted function
note: see declaration of 'Foo<float>::Foo'

I looked around and I suspected that there might one of the two reasons this.

1) Copy constructor member for std::mutex is deleted

2) This which I thought might be similar to what I am seeing.

Which one is it? What can I do to bypass this error thrown by VS 2015 Update 2 compiler?

UPDATE:Updated the constructor which takes in some parameters that are needed to be passed to Foo_typedef.


Solution

  • You need to construct the element in place using the constructor:

    Foo_typedef Func::static_array[2] = { {2, 3}, {2, 3} };
    

    With this, there are no copy or move because the two elements are constructed in place.

    The standard says (§8.5.1/2 [dcl.init.aggr], emphasis is mine):

    When an aggregate is initialized by an initializer list, [...] the elements of the initializer list are taken as initializers for the members of the aggregate [...].

    In your case, it means that Foo_typedef(2,3) will be taken as an initializer for your Foo_typedef and thus a copy will be needed. In the code I gave, {2, 3} will be taken as an initializer and the corresponding constructor will be called (no copy).