0

I converted some methods from argument type const std::set<>& to const boost::container::flat_set<>& with the same template types being passed. Now I have to change every occurrence of calls to these methods where the argument was {} and have to replace them with typename().

Why is this, and is there some easier way?

boost_1_60_0 being used -- don't blame me!

To compile:

g++ -std=c++11 test_set.cpp -D__FLAT__

or

g++ -std=c++11 test_set.cpp

The error message is clear -- and I couldn't read the original.

I guess the {} can only be interpreted as an argument list, as the type is unknown.

#include <set>
#include <map>
#include <boost/container/flat_set.hpp>
#include <boost/container/flat_map.hpp>

#ifndef __FLAT__
typedef std::map<int, int> MAP;
typedef std::set<MAP> SET;
#else
typedef boost::container::flat_map<int, int> MAP;
typedef boost::container::flat_set<MAP> SET;
#endif

static void show(const SET&)
{
}

int main(int, char**)
{   
    //SET s({});
    show({});
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Frank Puck
  • 467
  • 1
  • 11
  • 1
    The type has an non-explicit initializer-list constructor, so `{}` as argument should be fine. See https://www.boost.org/doc/libs/1_60_0/doc/html/boost/container/flat_set.html. Please provide a proper [mre] including the error message it generates. – user17732522 Oct 21 '22 at 21:08
  • 1
    Compiler explorer doesn't support Boost 1.60, but with 1.64 it works fine: https://godbolt.org/z/YcqWbvnPK – user17732522 Oct 21 '22 at 21:43
  • @user17732522 which is strange, because the documentation for boost 1.64 still has it as explicit, changing in 1.66 to non-explicit – Caleth Oct 26 '22 at 10:09
  • @Caleth Right, I forgot that the default constructor should be chosen for an empty `{}`, so the initializer-list constructor doesn't matter. It seems that older GCC versions accept the `explicit` default constructor in this case and that it wasn't clear how to handle this situation. I think this is related to https://cplusplus.github.io/CWG/issues/1518.html. – user17732522 Oct 26 '22 at 10:36
  • Testing on compiler explorer, GCC 4.8 and earlier (in all minor revisions) accept the `explicit` default constructor, while GCC 4.9 and later (in all minor revisions) don't. So that makes me question whether the `g++-4.8` tag is really correct. – user17732522 Oct 26 '22 at 10:39

1 Answers1

0

As mentioned in a comment, constructors for std::set are non-explicit while boost::container::flat_set are explicit.

Explicit constructors require you to explicitly indicate the type, and when you do {} you are not.

Also, in the commented line you are first constructing the object and then calling the copy constructor of SET. As the Boost's container has an explicit constructor, compiler is not able to deduce the type you need there so it cannot deduce that the {} was for creating a SET.

You can fix it in several ways:

SET s{};
SET s{SET{}}; // ridiculous usage, just to illustrate the problem
show(SET{});
cbuchart
  • 10,847
  • 9
  • 53
  • 93