Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is an integer being promoted via an explicit constructor?

This code

#include <cstdint>

constexpr uint32_t ticksPerSecond = 100000;

struct timemeasure {
    constexpr explicit timemeasure(uint64_t c) : ticks(c) { }
    uint64_t ticks;
    constexpr timemeasure() : ticks(0) { }
};

struct time : timemeasure {
    static volatile time now;

    constexpr time() : timemeasure() { }
    explicit time(uint64_t c) : timemeasure(c) { }

    // Needed for `x = time::now`
    explicit time(const volatile time &t) : timemeasure(t.ticks) { }
    time& operator=(volatile time t) { ticks = t.ticks; return *this; }
};

inline time foo(const time& t) { return time(t.ticks + 1); }

gives the compilation error:

prog.cpp: In function ‘time foo(const time&)’:
prog.cpp:22:57: error: no matching function for call to ‘time::time(time)’
prog.cpp:22:57: note: candidate is:
prog.cpp:14:15: note: constexpr time::time()
prog.cpp:14:15: note:   candidate expects 0 arguments, 1 provided

Why is time::time(time) trying to be called? Surely the uint64_t is not allowed to be promoted?

like image 652
Eric Avatar asked Jun 20 '13 16:06

Eric


1 Answers

The copy constructor of time is marked as explicit, and when returning a value from a function, a temporary is copy-initialized from that value. Paragraph 8.5/15 of the C++11 Standard specifies:

The initialization that occurs in the form

T x = a;

as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization. [...]

However, constructors marked as explicit are not considered in the context of a copy-initialization (see 13.3.1.4/1 and 13.3.1.5/1), hence the error.

like image 147
Andy Prowl Avatar answered Nov 15 '22 01:11

Andy Prowl