Здравствуйте, B0FEE664, Вы писали:
BFE>Вопрос из сабжа на засыпку:
Я бы предположил, что в какой-то из реализаций std::chrono::duration что-то перемудрили с конструкторами и теперь приходится форсировано приводить фактические параметры к rvalue выражениям, чтобы выбирался нужный конструктор.
BFE>Ответ можно найти в С++17 12.2.3.2/3
Вот этого не понял. Может у меня уже драфт устарел и пора мне обновляться? У меня в этом пункте вот что:
If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (8.20). The member shall still be defined in a namespace scope if it is odr-used (6.2) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.1). Declarations of other static data members shall not specify a brace-or-equal-initializer.
--
Не можешь достичь желаемого — пожелай достигнутого.
BFE>>Ответ можно найти в С++17 12.2.3.2/3
R>Вот этого не понял. Может у меня уже драфт устарел и пора мне обновляться? У меня в этом пункте вот что:
R>
R>If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (8.20). The member shall still be defined in a namespace scope if it is odr-used (6.2) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.1). Declarations of other static data members shall not specify a brace-or-equal-initializer.
Байнд ссылки (в параметрах конструктора) напрямую к A::TIMEOUT это odr-use.
А lvalue-to-rvalue conversion в вычислении выражения `+A::TIMEOUT` это не odr-use.
Здравствуйте, B0FEE664, Вы писали:
BFE>Вопрос из сабжа на засыпку:
Да всё просто: A::TIMEOUT — это имя старой переменной, её нельзя рвалуить, а +A::TIMEOUT — это выражение, вычисляющее новую переменную, которую можно мувить и рвалуить.
Здравствуйте, rg45, Вы писали:
R>Я бы предположил, что в какой-то из реализаций std::chrono::duration что-то перемудрили с конструкторами и теперь приходится форсировано приводить фактические параметры к rvalue выражениям, чтобы выбирался нужный конструктор.
BFE>>Ответ можно найти в С++17 12.2.3.2/3 R>Вот этого не понял. Может у меня уже драфт устарел и пора мне обновляться? У меня в этом пункте вот что:
Выделил: R>
R>If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (8.20). The member shall still be defined in a namespace scope if it is odr-used (6.2) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.1). Declarations of other static data members shall not specify a brace-or-equal-initializer.
Это значит, что надо
либо добавить строку вне класса:
//staticconst unsigned A::TIMEOUT;
либо переписать
void boo()
{
auto t = A::TIMEOUT;
foo( std::chrono::milliseconds(t) );
}
либо можно просто добавить '+' и тогда по ссылке будет передаваться не сам объект, а его копия.
Здравствуйте, watchmaker, Вы писали:
W>А что вариант с inline не рассматривается?
Бываю такие конторы, которые только-только начали переходить на С++11...
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Что это, как не живительная сила rvalue ссылок? σ>>А они тут при чём?
BFE>А разве это не rvalue ссылка которая преобразуется к обычной ссылке?
Правильнее сказать, rvalue выражение, которое материализуется во временный объект, который в свою очередь биндится к константной lvalue ссылке. Обычная схема, существовавшая еще до появления rvalue ссылок.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Правильнее сказать, rvalue выражение, которое материализуется во временный объект, который в свою очередь биндится к константной lvalue ссылке. Обычная схема, существовавшая еще до появления rvalue ссылок.
Разве по стандарту 98 можно было передать временный объект по ссылке? (Помню, что MS компилятор отходил от стандарта в этом случае)
Здравствуйте, B0FEE664, Вы писали:
R>>Правильнее сказать, rvalue выражение, которое материализуется во временный объект, который в свою очередь биндится к константной lvalue ссылке. Обычная схема, существовавшая еще до появления rvalue ссылок.
BFE>Разве по стандарту 98 можно было передать временный объект по ссылке? (Помню, что MS компилятор отходил от стандарта в этом случае)
Ну в C++03 то уж точно можно было.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, B0FEE664, Вы писали:
BFE>>Разве по стандарту 98 можно было передать временный объект по ссылке? (Помню, что MS компилятор отходил от стандарта в этом случае)
R>Ну в C++03 то уж точно можно было.
И в 98 тоже:
8.5.3 References /5
. . .
— If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is referencecompatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementationdefined):
— The reference is bound to the object represented by the rvalue (see 3.10) or to a subobject within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a subobject within the temporary.93)
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
BFE>>>Разве по стандарту 98 можно было передать временный объект по ссылке? (Помню, что MS компилятор отходил от стандарта в этом случае) R>>Ну в C++03 то уж точно можно было. R>И в 98 тоже:
Хмм. Действительно. Для константных ссылок так было всегда. Значит я ошибся и rvalue ни при чём.
Хз, это какие-то заморочки компилятора. Ideone же собирает. Даже если это член класса.
(Ровно до того момента, пока мы не попытаемся явно взять адрес этой константы).
Здравствуйте, Кодт, Вы писали:
К>Зачем плюс? Незачем, это избыточный код. BFE>>Что это, как не живительная сила rvalue ссылок? К>Это живительная сила explicit конструктора.
Как мне кажется, здесь избыточная сложность примера мешает взглянуть в корень. Упрощаем, насколько это возможно. Начинаем с работающего варианта:
struct A {
static const int value = 42;
};
void foo(const int&) {}
int main() {
foo(+A::value);
}
Стоит убрать "плюсик", как начинает валиться с ошибкой: "undefined reference to `A::value'". А происходит это потому, что выражения "A::value" и "+A::value" имеют разные типы: первое — lvalue, второе — rvalue. Использование первого выражения рассматривается как odr-used и требует, согласно 12.2.3.2/3, чтобы статический член был определен в пространстве имен.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, σ, Вы писали:
BFE>>>Что это, как не живительная сила rvalue ссылок? σ>>А они тут при чём?
BFE>А разве это не rvalue ссылка которая преобразуется к обычной ссылке?
То чувство, когда притащил код с демонстрацией тонкостей плюсов, но не отличаешь Гоголя от Гегеля rvalue от rvalue reference