Руководство по выводу аргумента шаблона для типа аргумента unique_ptr?

Можно ли написать руководство по выводу, чтобы экземпляр Simple можно было объявить без аргументов шаблона? Я пробовал, но не могу получить правильную форму для извлечения типа элемента std::unique_ptr.

//------------------------------------------------------------------------------
template< class T >
class Simple
{
public:
    Simple( std::unique_ptr< T >& u ) :
    u_( u )
    {}
private:
    std::unique_ptr< T >& u_;
};

class MyThing
{};

int main()
{
    std::unique_ptr< MyThing > upSimple;
    Simple( upSimple ); // error C2955: 'Simple': use of class template requires template argument list
}

person Armbie    schedule 03.10.2018    source источник
comment
Снова грянет самый неприятный разбор!   -  person Rakete1111    schedule 04.10.2018
comment
Как только вы исправите досадную ошибку синтаксического анализа, он все равно не скомпилируется — MSVC еще не поддерживает CTAD?   -  person Barry    schedule 04.10.2018
comment
Следуя наблюдениям @rakete, это компилируется (под gcc): Simple s ( upSimple );, см.: wandbox.org/permlink/V4bp2fsfk49cYMSd< /а>   -  person Paul Sanders    schedule 04.10.2018
comment
@Barry Последний MSVC делает. godbolt.org/z/Z1pXRo   -  person Rakete1111    schedule 04.10.2018
comment
@ Rakete1111 Я никогда не знаю, какой MSVC выбрать из этого списка, лол. Отмеченный :-)   -  person Barry    schedule 04.10.2018
comment
@Barry Не забудь последний флаг! :)   -  person Rakete1111    schedule 04.10.2018
comment
Хорошо, да, ваши комментарии привели меня к исправлению! Замена Simple( upSimple ) на Simple{ upSimple } и установка стандарта языка C++ на /std:c++17 в настройках проекта позволяет скомпилировать его как есть! Спасибо @Rakete1111!   -  person Armbie    schedule 04.10.2018
comment
Может ли кто-нибудь написать ответ на это вместо последовательности комментариев? :п   -  person Yakk - Adam Nevraumont    schedule 04.10.2018


Ответы (1)


Можно ли написать руководство по дедукции, чтобы экземпляр Simple можно было объявить без аргументов шаблона? Я пробовал, но не могу получить правильную форму для извлечения типа элемента std::unique_ptr.

Проблема в другом.

Неявно сгенерированные руководства по дедукции прекрасно способны извлечь правильный параметр шаблона типа для Simple.

Как указал Rakete1111, это своего рода «самая неприятная проблема разбора».

Пишу

Simple( upSimple );

ваше намерение состояло в том, чтобы получить инициализацию безымянного временного объекта типа Simple (Simple<MyThing>, благодаря новым неявно сгенерированным руководствам по дедукции C++17), инициализированного объектом upSimple.

К сожалению, компилятор (visual-c++, но то же самое с g++ и clang++) интерпретирует это как объявление новой переменной (обратите внимание, что скобки, объявляющие переменные C++, излишни, но вполне допустимы; с помощью int (i); вы объявляете переменную i типа int) назовите upSimple и введите Simple.

Это дает ошибку, потому что

(1) upSimple определено в предыдущей строке, поэтому у нас есть повторное объявление upSimple

(2) неявно сгенерированные руководства по выводу не могут без аргумента конструктора вывести аргумент шаблона T для Simple.

Чтобы избежать этой двусмысленности и получить инициализацию объекта Simple<MyThing>, вы можете сохранить значение в переменной с помощью

auto s = Simple(upSimple);

или также с

Simple s(upSimple);

поэтому компилятор больше не может интерпретировать строку как объявление переменной upSimple.

Если вам действительно нужен безымянный временный объект, вы можете использовать универсальную инициализацию (вы можете использовать фигурные скобки вместо скобок)

//.....V..........V
Simple { upSimple };

это нельзя интерпретировать как объявление переменной.

И, да: также может быть полезно навязывание использования нового стандарта С++ 17 (через /std:c++17 или -std=c++17 или в зависимости от того, что требуется от конкретного компилятора).

person max66    schedule 04.10.2018