简体   繁体   English

关于 std::make_pair & std::atomic_bool 的问题

[英]Question about std::make_pair & std::atomic_bool

Why this code snippet does not compile with gcc 4.9.0 , whereas it works well with gcc 12.1 .为什么这个代码片段不能与gcc 4.9.0一起编译,而它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:这是gcc 4.9.0抱怨的内容:

<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?有人可以阐明其背后的原因吗?

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. map::insert正在尝试调用此转换构造函数。 The behavior changed in GCC 6. GCC 6 中的行为发生了变化。

This is N4387 .这是N4387 See change 6. Previously, this constructor had:请参阅更改 6。以前,此构造函数具有:

This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.此构造函数不应参与重载决议,除非 U 可隐式转换为 first_type 并且 V 可隐式转换为 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.除非 is_constructible<first_type, U&&>::value 为真且 is_constructible<second_type, V&&>::value 为真,否则此构造函数不应参与重载决议。

The GCC commit is here . GCC 提交在这里

This was applied as a DR, so it changed in all standards modes.这是作为 DR 应用的,因此它在所有标准模式中都发生了变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM