Как предоставить руководство по вычету для вложенного класса шаблона?

Согласно [temp.deduct.guide/3 ]:

(...) Руководство по дедукции должно быть объявлено в той же области, что и соответствующий шаблон класса, и для шаблона класса-члена с тем же доступом. (...)

Но приведенный ниже пример, похоже, не компилируется как в [gcc], так и в [clang].

#include <string>

template <class>
struct Foo {
    template <class T>
    struct Bar {
        Bar(T) { }
    };
    Bar(char const*) -> Bar<std::string>;
};

int main() {
    Foo<int>::Bar bar("abc");
    static_cast<void>(bar);
}

Каков правильный синтаксис руководства по выводу для вложенного класса шаблона? Или, может быть, это правильный, но он еще не поддерживается компиляторами?


Подобный синтаксис, но без вложенного класса, отлично компилируется как в gcc, так и в clang:

#include <string>

template <class T>
struct Bar {
    Bar(T) { }
};
Bar(char const*) -> Bar<std::string>;

int main() {
    Bar bar("abc");
    static_cast<void>(bar);
}

person W.F.    schedule 07.09.2017    source источник
comment
В GCC это ошибка, поскольку он думает, что вы объявляете функцию.   -  person Some programmer dude    schedule 07.09.2017
comment
@Someprogrammerdude Я не уверен, что это правильный синтаксис - в стандарте нет соответствующего примера, но он упоминает ситуацию ...   -  person W.F.    schedule 07.09.2017
comment
Руководство по выводу вложенных шаблонов работает, если родительский класс не является шаблоном ....   -  person AndyG    schedule 07.09.2017
comment
@AndyG да, синтаксис кажется правильным   -  person W.F.    schedule 07.09.2017


Ответы (2)


[temp.deduct.guide] включает предложение :

deduction-guide должен быть объявлен в той же области, что и соответствующий шаблон класса, и для шаблона класса-члена с тем же доступом.

Это говорит о том, что ваш пример должен работать - руководства по дедукции явно поддерживаются для шаблонов классов-членов, если они объявлены в той же области видимости и доступа (это будет область видимости класса и public - проверка и проверка).

Это ошибка gcc 79501 ​​ (поданная Ричардом Смитом).

person Barry    schedule 07.09.2017
comment
@ W.F. Ваш внешний класс - это шаблон класса, пример с этой ошибкой проще. Должен сообщать об ошибке llvm. - person Barry; 07.09.2017
comment
Да, это определенно говорит о том, что синтаксис должен быть правильным. Тогда я попробую записать ошибку ... - person W.F.; 07.09.2017
comment
Только что отправлено об ошибке llvm 34520. - person W.F.; 07.09.2017
comment
По словам Ричарда, это дефект. См. Комментарий № 1 к PR35107. - person Rakete1111; 09.11.2017

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

Здесь, на Godbolt

Ключ состоит в том, чтобы справиться с поведенческими расхождениями между GCC и Clang, добавив директиву для конкретного компилятора.
Это неоптимально, но если вы заблокированы в своем проекте, это может помочь вы ждете патча компилятора (ов).

См. Мой ответ на это сообщение: https://stackoverflow.com/a/66888013/10883423

#include <string>

template <class>
struct Foo {
    template <class T>
    struct Bar {
        Bar(T) { }
    };
    #if __clang__
    Bar(char const*) -> Bar<std::string>;
    #endif
};

void instanciate_symbols()
{
    [[maybe_unused]] auto bar = Foo<int>::Bar{"abc"};
}
person Guss    schedule 31.03.2021