Opened 8 years ago

Closed 3 months ago

Last modified 3 months ago

#5419 closed Patches (wontfix)

assign fails with C++0x compilers

Reported by: Chris Jefferson Owned by: James E. King, III
Milestone: Boost 1.69 Component: assign
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc:

Description

Assign is failing to compile with a clang and libc++ when in C++0x mode. I believe this is because C++0x has two operator= for each container, for example vector has:

operator=(const std::vector<T>&) operator=(initialiser_list<T>)

And the technique of using (from list_of.hpp)

template< class Container >

operator Container() const {

return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();

}

Can't choose between these two options.

I don't know the best, or really any good way, to fix this unfortunately.

Attachments (3)

list_of_cxx0x.patch (604 bytes) - added by Michel MORIN <mimomorin@…> 8 years ago.
A patch for list_of.hpp (against trunk)
list_of_cxx0x_2.patch (1018 bytes) - added by Michel MORIN <mimomorin@…> 8 years ago.
A new patch for list_of.hpp (previous patch is incomplete).
assign_cxx0x.patch (3.3 KB) - added by Michel MORIN <mimomorin@…> 7 years ago.
A patch for boost/assign/list_of.hpp and libs/assign/test/. This patch includes the previous fixes.

Download all attachments as: .zip

Change History (15)

comment:1 Changed 8 years ago by anonymous

Hm. That could be problematic.

Since initializer lists only take on template argument, we should be able to do the following:

replace

template< class Container > operator Container() const

with

template< template<class,class> Container, class T, class A > operator Container<T,A>() const

Furthermore, this only takes care of templates with two arguments like standard sequence. Therefore, we also need to add overloads with 3 and four arguments.

A bigger problem arises with something like boost::multi_index_container which may have many template arguments ... hm ... maybe the C++11 solution is to use variadic templates to cover all cases with more than one template argument.

If you can make a patch and test it, I'd be happy to apply it.

regards

-Thorsten

Changed 8 years ago by Michel MORIN <mimomorin@…>

Attachment: list_of_cxx0x.patch added

A patch for list_of.hpp (against trunk)

comment:2 Changed 8 years ago by Michel MORIN <mimomorin@…>

Attached a patch for this ticket.
I use C++0x's "default template arguments for function templates" feature to SFINAE out the conversion operator to initializer_list. (While Container is required to have difference_type nested-type, initializer_list does not have it.

Changed 8 years ago by Michel MORIN <mimomorin@…>

Attachment: list_of_cxx0x_2.patch added

A new patch for list_of.hpp (previous patch is incomplete).

comment:3 Changed 8 years ago by Michel MORIN <mimomorin@…>

A new patch attached. The previous patch only fixes generic_list, but this patch fixes both generic_list and static_generic_list.

Changed 7 years ago by Michel MORIN <mimomorin@…>

Attachment: assign_cxx0x.patch added

A patch for boost/assign/list_of.hpp and libs/assign/test/. This patch includes the previous fixes.

comment:4 Changed 7 years ago by Michel MORIN <mimomorin@…>

A patch attached. I believe it's the final patch for this problem ;)

With this patch, the test (libs/assign/test) runs successfully on

  • gcc-4.3.6, gcc-4.4.6, gcc-4.5.3, gcc-4.6.1
  • clang (trunk)

The test runs in both C++03 and C++0x modes.

The previous patch fixes the problem of ambiguity with std::initializer_list<T>. However, in order to pass all the test, this is not enough. I added the following fixes:

  • (boost/assign/list_of.hpp) The ambiguity problem is also happened with std::allocator<T>. Adding dummy template parameter to the conversion function can avoid this ambiguity:
    template
    < 
        class Container
      , class Dummy1 = typename Container::difference_type
      , class Dummy2 = typename Container::iterator
    >
    operator Container() const
    {
        // ...
    }
    
    std::initializer_list<T> is SFINAE'ed out by Dummy1 and std::allocator<T> is SFINAE'ed out by Dummy2.
  • (libs/assign/test/std.cpp) In C++0x mode of some compilers, the code
    using namespace std;
    // ...
    typedef pair<string,int> tuple; 
    
    interact badly with std::tuple<Args…> and causes compiler errors. Simply changing the typedef fixes the problem:
    using namespace std;
    // ...
    typedef pair<string,int> two; 
    
  • (libs/assign/test/list_inserter.cpp) In C++0x mode of gcc-4.3, std::vector<T> does not have
    void push_back(const T&);
    
    but it has
    template <typename Args...>
    void push_back(Args&&...);
    
    So the code
    push_back_t push_back_func = &vector<int>::push_back;
    
    should be changed to
    push_back_t push_back_func = &vector<int>::push_back<const int&>;
    

comment:5 Changed 7 years ago by Michel MORIN <mimomorin@…>

The rationale for using SFINAE by "default template arguments for function templates" rather than restricting the number of template parameters by variadic templates is that

  • User-defined containers can have only one template parameter. In this case, the variadic template approach breaks the existing code.
  • Variadic templates cannot handle ordinary (type) template parameters and non-type template parameters simultaneously. This means that we have to define different overloads for different patterns of non-type template parameters. It's a mess.

comment:6 Changed 7 years ago by Michel Morin <mimomorin@…>

Type: BugsPatches

comment:7 Changed 5 years ago by Adam Romanek <romanek.adam@…>

Why was the type of this ticket changed to Patches? For me it's kind of a bug. The problem appears when trying to compile a code that uses Boost.Assign, in C++11 mode (in my case the problem is with assignment boost::assign::map_list_of() to boost::unordered_map).

What are the chances to push this forward? Is there any workaround? I may provide a test case if it helps.

comment:8 Changed 3 months ago by James E. King, III

Owner: changed from Thorsten Ottosen to James E. King, III

comment:9 Changed 3 months ago by James E. King, III

Resolution: wontfix
Status: newclosed

Please use gcc 4.8 or later.

comment:10 Changed 3 months ago by James E. King, III

Milestone: To Be DeterminedBoost 1.69

comment:11 Changed 3 months ago by James E. King, III

So it looks like I cannot reopen this, but it was reported in #7364 so I will submit a PR

Note: See TracTickets for help on using tickets.