2013-06-20 5 views
5

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); } 

дает ошибку компиляции:

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 

Почему time::time(time) пытается назвать? Неужели uint64_t не может быть повышена?

+0

Почему все 'volatile' в примере? Обновлен ли 'now' несколькими потоками? – Casey

+0

@Casey: Он обновляется одним потоком и читается другими. – Eric

+0

Есть ли опция C++ 11? Использование 'std :: atomic' для' now' позволило бы избежать всего этого беспорядка с помощью летучего оператора копирования и присваивания ([как это] (http://ideone.com/mRiXMm)). – Casey

ответ

7

Копия конструктор time отмечен как explicit, и при возврате значения из функции, является временным копия инициализируется от этого значения. Пункт 8.5/15 из C++ 11 Стандарта устанавливает:

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. [...]

Однако конструкторы помечены как explicit не рассматривается в контексте копировальной инициализации (см 13.3.1.4/1 и 13.3.1.5/1), следовательно, ошибка.

+0

Сам пришел к такому выводу – Eric

+0

@ Эрик: Я знаю это чувство , спрашивая других, часто является лучшим способом * действительно * спрашивать себя;) –

+0

Ответы правильны по причине, но терпят неудачу в аргументе. Проблема заключается не в конструкторе, который берет 'uint64_t', этот конструктор называется ** явно ** в коде. Проблема заключается в том, что конструктор копирования является «явным». –

0

Вы не можете вернуть time по значению из foo так time не имеет доступный конструктор копирования: конструктор из volatile const time& не совпадает. Выбросьте a:

time(const time&) = default; 
+1

Он будет соответствовать, но не проверен, потому что он «явный». – aschepler

+0

@aschepler Не согласно [gcc 4.7.2] (http://ideone.com/ZwCO6t): 'нет известного преобразования для аргумента 1 от 'time' до 'const volatile time &'' – Casey

+0

О, право. Временное не может связываться с 'const volatile X &'. – aschepler