Постоянство вывода шаблона класса С++ 17

Я пытаюсь использовать новый вывод шаблона класса С++ 17, и все это работает нормально, пока я не применяю const. Это небольшой пример проблемы, с которой я сталкиваюсь:

#include <type_traits>

template <typename T>
struct X
{
    T _data;

    X(void) = default;
    X(T && data) : _data{ data } {}

    constexpr bool const_x(void) { return false; }
    constexpr bool const_x(void) const { return true; }
};

template <typename T>
X(T &&) -> X<std::remove_reference_t<T>>;

int main(void)
{
    X<int> a;
    const X<int> b{};

    X c{ 10 };
    const X d{ 10 };

    static_assert(!a.const_x());
    static_assert(b.const_x());

    static_assert(!c.const_x());
    static_assert(d.const_x()); // assert fails
}

оказывается, что когда const X выводит свои типы, константность не выполняется. Я знаю, что это возможно:

template <typename T>
X(T &&) -> const X<std::remove_reference_t<X>>;

но это сделало бы каждый выводимый тип const X.

Если у кого-то есть информация или помощь, буду очень признательна!

ИЗМЕНИТЬ Я использую GCC-7.1.0


person Fletcher Blight    schedule 25.07.2017    source источник
comment
У godbolt.org/g/kRdTpJ у clang нет проблем с вашим кодом. В транке gcc также нет проблем: godbolt.org/g/TpneVq выглядит как ошибка компилятора. Предположительно, вы пытались использовать gcc 7.1? godbolt.org/g/j6W3dB (сбой в этой строке)   -  person xaxxon    schedule 25.07.2017
comment
Есть ли у вас ошибки при компиляции? Или только во время исполнения?   -  person Fenixrw    schedule 25.07.2017
comment
@Fenixrw это статическое утверждение, которое не работает - это только проблема времени компиляции   -  person xaxxon    schedule 25.07.2017
comment
@xaxxon полностью компилируется в clang?   -  person Fletcher Blight    schedule 25.07.2017
comment
@FletcherBlight я разместил ссылку... Вот ссылка с включенной опцией ссылки.. godbolt.org/g/ qm77Mx   -  person xaxxon    schedule 25.07.2017
comment
@xaxxon спасибо за это, похоже, это ошибка компилятора   -  person Fletcher Blight    schedule 25.07.2017
comment
Поддержка C++17 по-прежнему несовершенна (7/2017) во всех выпущенных компиляторах. Держитесь 14-го года, если хотите стабильности.   -  person xaxxon    schedule 25.07.2017


Ответы (1)


Это ошибка компилятора, а именно ошибка gcc 80990. Здесь есть две отдельные части - дедукция и const. Декларация:

const X d{ 10 };

сначала выполнит вывод аргумента шаблона класса, чтобы выбрать X специализацию d (то есть X<int> из-за руководства по выводу), а затем const добавится поверх этого (так что X<int> const).


Обратите внимание также, что это:

template <typename T>
X(T &&) -> const X<std::remove_reference_t<X>>;

плохо сформирован. Вы не можете использовать там cv-qualifiers.

person Barry    schedule 25.07.2017