Igor Krechetov
Igor Krechetov

Reputation: 33

Compilation issue when using std::pair as an argument for operator=

I'm stuck for hours trying to figure out why the following code doesn't compile and would appreciate if someone could point out what I'm missing.

Code is just a simplified example of compilation issue I'm having in a real project code.

#include <map>
#include <string>
#include <utility>

class A
{
public:
   A() = default;
   A(const A& v) = default;
   A(A&& v) = default;
   A& operator=(const A& v) = default;
   
   A& operator=(const std::pair<A, A>& v)
   {
      return *this;
   }
};

void func(const std::pair<int, A>& obj);

int main(int argc, char *argv[])
{
    std::pair<int, A> obj;
    func(obj);
    return 0;
}

void func(const std::pair<int, A>& obj)
{
    A a, b;
    a = b;
}

The issue seems to be related with "A& operator=(const std::pair<A, A>& v)". What confuses me is that if I move function "void func(...)" before main() everything compiles correctly.

Compiled using gcc (C++17). The error I'm getting looks like this:

In file included from /usr/include/c++/7/bits/move.h:54:0,
                 from /usr/include/c++/7/bits/stl_pair.h:59,
                 from /usr/include/c++/7/bits/stl_algobase.h:64,
                 from /usr/include/c++/7/bits/stl_tree.h:63,
                 from /usr/include/c++/7/map:60,
                 from main.cpp:1:
/usr/include/c++/7/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_assignable<A>, std::is_copy_assignable<A> >’:
/usr/include/c++/7/bits/stl_pair.h:378:7:   required from ‘struct std::pair<A, A>’
/usr/include/c++/7/type_traits:1259:45:   required by substitution of ‘template<class _Tp1, class _Up1, class> static std::true_type std::__is_assignable_helper<A&, const A&>::__test<_Tp1, _Up1, <template-parameter-1-3> >(int) [with _Tp1 = A&; _Up1 = const A&; <template-parameter-1-3> = <missing>]’
/usr/include/c++/7/type_traits:1268:40:   required from ‘class std::__is_assignable_helper<A&, const A&>’
/usr/include/c++/7/type_traits:1273:12:   required from ‘struct std::is_assignable<A&, const A&>’
/usr/include/c++/7/type_traits:1285:12:   required from ‘struct std::__is_copy_assignable_impl<A, true>’
/usr/include/c++/7/type_traits:1291:12:   required from ‘struct std::is_copy_assignable<A>’
/usr/include/c++/7/type_traits:143:12:   required from ‘struct std::__and_<std::is_copy_assignable<int>, std::is_copy_assignable<A> >’
/usr/include/c++/7/bits/stl_pair.h:378:7:   required from ‘struct std::pair<int, A>’
<span class="error_line" onclick="ide.gotoLine('main.cpp',23)">main.cpp:23:20</span>:   required from here
/usr/include/c++/7/type_traits:143:12: error: incomplete type ‘std::is_copy_assignable’ used in nested name specifier
     struct __and_<_B1, _B2>
            ^~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
                 from /usr/include/c++/7/bits/stl_tree.h:63,
                 from /usr/include/c++/7/map:60,
                 from main.cpp:1:
/usr/include/c++/7/bits/stl_pair.h: In instantiation of ‘struct std::pair<A, A>’:
/usr/include/c++/7/type_traits:1259:45:   required by substitution of ‘template<class _Tp1, class _Up1, class> static std::true_type std::__is_assignable_helper<A&, const A&>::__test<_Tp1, _Up1, <template-parameter-1-3> >(int) [with _Tp1 = A&; _Up1 = const A&; <template-parameter-1-3> = <missing>]’
/usr/include/c++/7/type_traits:1268:40:   required from ‘class std::__is_assignable_helper<A&, const A&>’
/usr/include/c++/7/type_traits:1273:12:   required from ‘struct std::is_assignable<A&, const A&>’
/usr/include/c++/7/type_traits:1285:12:   required from ‘struct std::__is_copy_assignable_impl<A, true>’
/usr/include/c++/7/type_traits:1291:12:   required from ‘struct std::is_copy_assignable<A>’
/usr/include/c++/7/type_traits:143:12:   required from ‘struct std::__and_<std::is_copy_assignable<int>, std::is_copy_assignable<A> >’
/usr/include/c++/7/bits/stl_pair.h:378:7:   required from ‘struct std::pair<int, A>’
<span class="error_line" onclick="ide.gotoLine('main.cpp',23)">main.cpp:23:20</span>:   required from here
/usr/include/c++/7/bits/stl_pair.h:378:7: error: ‘value’ is not a member of ‘std::__and_, std::is_copy_assignable >’
       operator=(typename conditional<
       ^~~~~~~~

Upvotes: 3

Views: 616

Answers (1)

Mestkon
Mestkon

Reputation: 4046

What you are experiencing now is a prime example of undefined behavior as the std::pair implementation depends on type_traits which are not defined for incomplete types.

Inside the scope of A but outside any member functions A is considered an incomplete type. You are trying to define a function which takes a std::pair<A, A>, and thus instantiate std::pair with an incomplete type.

This is not the case if A had been a templated type as functions of class templates are not instantiated until they are actually invoked.

Upvotes: 4

Related Questions