Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"chosen constructor is explicit in copy-initialization error" with clang++ 4.2

I have clang++ 4.2

Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix

When I tried to compile this c++11 code:

class ContextSummary {
    int id;
    int hops;
    std::map<std::string, int> db {};
    std::time_t timestamp;

ContextSummary(int id, const std::map<std::string, int>& db = {}, int hops = 3, std::time_t timestamp = 0)
{
    this->id = id;
    this->db = db;
    this->hops = hops;
    this->timestamp = timestamp;
}

I got this error message. The code works fine with g++4.8

error: 
      chosen constructor is explicit in copy-initialization
  ...id, const std::map<std::string, int>& db = {}, int hops = 3, std::time_t...

                                           ^    ~~

Is this clang++ bug? How can I bypass this error?

like image 758
prosseek Avatar asked Jun 23 '13 18:06

prosseek


1 Answers

Copying what I said in my comment

This is http://cplusplus.github.io/LWG/lwg-active.html#2193 . I'm not sure whether the "proposed resolution" or something equivalent makes it into C++14 or not. The fact whether or not value initialization using explicit default constructors in a copy initialization context is wellformed or not itself is also a core-language DR http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518 , which explains possibly cross-compiler differences.

If your implementation implements http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1494 and the following would be valid syntax for a default argument you could have done

const std::map<std::string, int>& db{}

Unfortunately, this is not allowed (I think the reason my be that passing an argument explicitly, you can't direct-initialize a parameter either, so why allow it for default arguments?). So it appears to me the only way is to explicit create it

const std::map<std::string, int>& db = std::map<std::string, int>{}

Decide whether you wanna get away with the redundancy at the cost of possibly more code. Some alternatives

const std::map<std::string, int>& db = decltype(ContextSummary::db){}
const std::map<std::string, int>& db_ = decltype(db){}
const std::map<std::string, int>& db = std::decay<decltype(db)>::type{}
like image 174
Johannes Schaub - litb Avatar answered Nov 09 '22 13:11

Johannes Schaub - litb