Это неправильное предупреждение? - PullRequest
4 голосов
/ 24 марта 2020

Давайте посмотрим на этот шаблон кода, который я вижу часто:

struct Foo
{
    template <typename T>
    T* as1() { /* ... */ }

    template <typename T>
    T* as2(T*) { /* ... */ }  
};   

Первый метод должен использоваться следующим образом:

    SomeComplexTypeAndNotAuto * a = foo.as1<SomeComplexTypeAndNotAuto>();

В то время как последний удобнее использовать поскольку вам не нужно повторять сложный тип:

    SomeComplexTypeAndNotAuto * a = foo.as2(a); 

Однако большинство компиляторов отклоняет второй случай с предупреждением Wuninitialized:

warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]

Совершенно очевидно, что переменная не является используется при инициализации, только его тип. Есть ли способ избежать этого предупреждения, не имея дело с адской прагмой для компилятора?

Редактировать:

Это не ясно из моего первоначального поста, но когда я писал SomeComplexTypeNotAuto, я имел в виду, что такой код вроде этого: auto a = foo.as2(a); не может быть разрешен, так как у вас есть для предоставления одного типа, чтобы компилятор мог его выводить.

Мой вопрос касался c того факта, что метод as2() является шаблоном, так как он должен быть виден во время специализации для типа T. Таким образом, компилятор может видеть, что аргумент T* даже не имеет имени, поэтому он не используется / не может использоваться внутри функции. Поэтому я не понимаю, почему он предупреждает о предупреждении «неиспользуемая переменная», поскольку ясно, что он не используется.

Ответы [ 3 ]

6 голосов
/ 24 марта 2020

Совершенно очевидно, что переменная не используется при инициализации

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

Это неправильное предупреждение?

Нет, предупреждение правильное.


Простое исправить это, превратив аргумент в ссылку:

T* as2(T*&)

Только убедитесь, что вы фактически не читаете указанное значение.

Поскольку C + 11, вы можете использовать вместо него auto .

2 голосов
/ 24 марта 2020

Предупреждение правильное.

a имеет неопределенное значение в своем инициализаторе, и передача его в качестве аргумента функции по значению требует его копирования, что требует чтения из него, значение которого не определено поведение.

Неважно, что вы не используете то, что было бы полученным значением.


Вы можете «исправить» его, запретив копирование (с помощью ссылочный аргумент), но в итоге вы получите очень странный и необычный код, который смущает ваших читателей. Я действительно не советую этот подход.

Просто прописать тип, в идеале сначала сделать его более коротким и читаемым.

Условно мы пропускаем повторяющееся имя типа, например:

auto* a = foo.as1<SomeComplexTypeAndNotAuto>();

(например, при использовании std::make_shared и друзей)

Кроме того, найдите шаблон посетителей.

1 голос
/ 24 марта 2020

Не ясно, что переменная не используется при инициализации. Внутри as2.

может произойти что угодно: если переменная не используется, не передавайте ее - используйте вместо этого явное создание экземпляра шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...