Home > database >  Question about std::make_pair & std::atomic_bool
Question about std::make_pair & std::atomic_bool

Time:06-27

Why this code snippet does not compile with gcc 4.9.0, whereas it works well with gcc 12.1.

The same code snippet is compiled with the same option.

Here is the code snippet:

#include<atomic>
#include<thread>
#include<map>
#include<vector>
#include<iostream>

class Demo{
public:
Demo()
{
    mp_.insert(std::make_pair(1, true));
    mp_.insert(std::make_pair(2, true));
    mp_.insert(std::make_pair(3, true));
}

int Get(const int& integer, bool& flag)
{
    const auto itr = mp_.find(integer);
    if( itr == mp_.end())
    {
        return -1;
    }
    else
    {
        flag = itr->second;
        return 0;
    }
}
int Set(const int& integer, const bool& flag)
{
    const auto itr = mp_.find(integer);
    if( itr == mp_.end())
    {
        return -1;
    }
    else
    {
        itr->second = flag;
        return 0;
    }
}

private:
std::map<int, std::atomic<bool>> mp_;
};

int main()
{
    Demo demo;

    std::vector<std::thread> vec;

    vec.push_back(std::thread([&demo](){
        //while(true)
        {
            for(int i=0; i<9; i  )
            {
                bool cur_flag = false;
                if(demo.Get(i, cur_flag) == 0)
                {
                    demo.Set(i, !cur_flag);
                }
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            }
        }
    }));

    vec.push_back(std::thread([&demo](){
        while(true)
        {
            for(int i=0; i<9; i  )
            {
                bool cur_flag = false;
                if(demo.Get(i, cur_flag)==0)
                {
                    std::cout << "(" << i << "," << cur_flag <<")" << std::endl;
                }
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
    })
    );

    for(auto& thread:vec)
    {
        thread.join();
    }
}

Here is what gcc 4.9.0 complains:

<source>: In constructor 'Demo::Demo()':
<source>:11:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
     mp_.insert(std::make_pair(1, true));
                                       ^
<source>:11:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
       template<typename _Pair, typename = typename
                                ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
       insert(std::initializer_list<value_type> __list)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const_iterator __position, const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(const_iterator __position, _Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note:   template argument deduction/substitution failed:
<source>:11:39: note:   cannot convert 'std::make_pair<int, bool>((* &1), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
     mp_.insert(std::make_pair(1, true));
                                       ^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_InputIterator __first, _InputIterator __last)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note:   template argument deduction/substitution failed:
<source>:11:39: note:   candidate expects 2 arguments, 1 provided
     mp_.insert(std::make_pair(1, true));
                                       ^
<source>:12:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
     mp_.insert(std::make_pair(2, true));
                                       ^
<source>:12:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
       template<typename _Pair, typename = typename
                                ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
       insert(std::initializer_list<value_type> __list)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const_iterator __position, const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(const_iterator __position, _Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note:   template argument deduction/substitution failed:
<source>:12:39: note:   cannot convert 'std::make_pair<int, bool>((* &2), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
     mp_.insert(std::make_pair(2, true));
                                       ^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_InputIterator __first, _InputIterator __last)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note:   template argument deduction/substitution failed:
<source>:12:39: note:   candidate expects 2 arguments, 1 provided
     mp_.insert(std::make_pair(2, true));
                                       ^
<source>:13:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
     mp_.insert(std::make_pair(3, true));
                                       ^
<source>:13:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:629:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:637:9: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
       template<typename _Pair, typename = typename
                                ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
       insert(std::initializer_list<value_type> __list)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:650:7: note:   no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
       insert(const_iterator __position, const value_type& __x)
       ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:679:7: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(const_iterator __position, _Pair&& __x)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:690:9: note:   template argument deduction/substitution failed:
<source>:13:39: note:   cannot convert 'std::make_pair<int, bool>((* &3), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
     mp_.insert(std::make_pair(3, true));
                                       ^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/map:61:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
         insert(_InputIterator __first, _InputIterator __last)
         ^
/opt/compiler-explorer/gcc-4.9.0/include/c  /4.9.0/bits/stl_map.h:705:9: note:   template argument deduction/substitution failed:
<source>:13:39: note:   candidate expects 2 arguments, 1 provided
     mp_.insert(std::make_pair(3, true));
                                       ^

Could somebody shed some light on the reason lies behind it?

CodePudding user response:

A reduced example is this:

struct destination_t {
  destination_t(int) {}
  destination_t(const destination_t&) = delete;
};

static_assert(std::is_constructible<
  std::pair<const int, destination_t>,
  std::pair<int, int>
  >::value, "");

map::insert is trying to call this converting constructor. The behavior changed in GCC 6.

This is N4387. See change 6. Previously, this constructor had:

This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.

That changed to:

This constructor shall not participate in overload resolution unless is_constructible<first_type, U&&>::value is true and is_constructible<second_type, V&&>::value is true.

The GCC commit is here.

This was applied as a DR, so it changed in all standards modes.

  • Related