0

I need help understanding GCC's problem with a templated-derived-structure.

The following is the basic content of a header file called Data.hpp:

template <typename T> struct DataContent {

    T *ptr;  

    // more stuff would go here but has been commented out for debug
};

template <typename T> struct Data : DataContent<T> {
public: 
    uint_fast64_t N=0;

    inline Data()  {};
    inline ~Data() { delete this->ptr; };

// ****************** PROBLEM METHOD LIVES HERE *******************
    inline Data &operator= (const T &rhs) { 
        for (uint_fast32_t n=0; n<N; n++ ) this->ptr[n] = rhs; 
        return *this; 
    };
// ****************************************************************

    // more stuff would go here but has been commented out for debug    
};

template class Data<float>;
template class Data<Data<float>>;

The system is a Intel i5, and the build command is:

g++-4.9 -Wall -fexceptions -march=corei7-avx -Wnon-virtual-dtor -Wshadow -Winit-self -Wfloat-equal -Winline -Weffc++ -std=c++11 -masm=intel -g -mfma -march=corei7-avx -mavx -O3 -std=c++11 -masm=intel -g -c

The error I get is

Data.hpp   error: use of deleted function ‘Data<float>& Data<float>::operator=(const Data<float>&)’
Data.hpp   note: ‘Data<float>& Data<float>::operator=(const Data<float>&)’ is implicitly deleted because the default definition would be ill-formed:

Any of the following actions, by themselves, makes this error go away:

  1. Eliminating explicit instantiation template class Data<Data<float>>
  2. Making Data a stand-alone structure, without use of the base structure DataContent
  3. Replacing, in the problem method, this->ptr[n]=rhs with this->ptr[n]=0 (without changing the function declaration)

Knowing all this, I'm still confused about the source of the problem. Frankly, I just plain confused as to why it is even trying to use the function

Data<float>& Data<float>::operator=(const Data<float>&)

anyways. I agree with the compiler that it is "ill-formed", but why it is trying to use it in the first place!? I expect the following functions to be used

Data<float>& Data<float>::operator=(const float&) 
Data<Data<float>>& Data<Data<float>>::operator=(const Data<float>&)

but not the one it is trying.

Equally important, it's confusing as to why fix #3 would help. Indeed, I would expect fix #3 to actually break the compilation when building the Data<Data<float>> class instantance.

Can someone please help? (BTW, fixes 1-3 are not viable solutions for end goals)

codechimp
  • 1,509
  • 1
  • 14
  • 21
  • The code you've just provided does compile while the previous one doesn't; can you roll back? – edmz May 19 '15 at 15:22

1 Answers1

1

When T = Data<float> (in template class Data<Data<float>>), the compiler doesn't know how to assign to Data<float> because it's an ADT and not built-in type such as float (in template class Data<float> with T = float). The compiler tries to auto-generate a default assignment operator but fails due to a const member and marks the method as delete.

Define a DataContent& operator=(const DataContent& rhs). A compiler like clang might help you in these situations because it's often able to produce clearer error messages than GCC's.

edmz
  • 8,220
  • 2
  • 26
  • 45
  • Thanks. That did the trick. I'm not sure why GCC is so confused, but okay. Does this mean I have to do this for all other assignment operators, like +=? What about non-assignment operators like +? – codechimp May 19 '15 at 17:46
  • 1
    That depends on how your class behaves and what's expected to do: if it's a value-like class (such as `string`, `complex` and so on) then it's advisable. Check [this](https://stackoverflow.com/questions/4421706/operator-overloading) out, particularly the second answer. – edmz May 19 '15 at 18:15