Опускать угловые скобки, когда шаблон имеет параметры по умолчанию - PullRequest
1 голос
/ 06 марта 2019

Предположим, у нас есть шаблон класса с параметром шаблона по умолчанию:

template <typename T = int>
class Foo {};

Мы можем опустить угловые скобки при создании переменной внутри функции:

int main()
{
    Foo a; // gets properly deduced as Foo<int>
}

Но мы не можемсделать это для переменных-членов:

struct S
{
    Foo a; // Deduce Foo<int>
};

У нас не может быть производных типов, таких как:

Foo* ptr; // Foo<int>*
Foo& ref; // Foo<int>&
int Foo::* mem_ptr; // int Foo<int>::*
std::function<Foo(const Foo&)> fn; // std::function<Foo<int>(const Foo<int>&)>

Мы не можем принимать параметры и возвращать их:

Foo Bar(const Foo&); // Foo<int> (*)(const Foo<int>&)

Почему?Это считается ошибкой в ​​стандарте?Есть предложение исправить это?Есть ли какие-либо проблемы с пропуском угловых скобок?

Мой вариант использования:

У меня есть шаблон класса, который предоставляет аргумент по умолчанию.Параметр шаблона - это функция только для экспертов, которой я сам никогда не пользуюсь, но он предназначен для тех 1% экспертов, которым нужна полная гибкость.Теперь для остальных 99% я хочу скрыть тот факт, что Foo на самом деле является шаблоном класса, но он не работает, потому что пользователи должны вводить Foo<> при объявлении его в качестве переменной-члена, текущее решение таково:

template <typename T = int>
class BasicFoo {};

using Foo = BasicFoo<>;

Но это усложняет код реализации и совсем не элегантно.

Ответы [ 2 ]

3 голосов
/ 06 марта 2019

Считается ли это ошибкой в ​​стандарте?

номер

Шаблоны - это именованная конструкция, которая генерирует другую конструкцию (классы / функции / переменные) на основе набора параметров. Имя шаблона не имя конструкции, которую он генерирует. Имя шаблона - это просто имя шаблона; чтобы назвать то, что генерирует шаблон, вы должны предоставить параметры шаблона.

Foo - имя шаблона; Foo<> - это имя класса, созданного этим шаблоном, и связанные с ним параметры шаблона.

Есть несколько мест, где C ++ позволяет использовать шаблон таким образом, чтобы его параметры выводились из последовательности выражений. Но это очень специфические места, созданные для удобства. Они не существуют для сокрытия того факта, что имя представляет шаблон, а не сгенерированную конструкцию.

Есть предложение исправить это?

Нет ничего сломанного, чтобы исправить. И в настоящее время нет предложений по добавлению изменений таким образом.

Есть ли какие-либо проблемы с пропуском угловых скобок?

Определите «актуальную проблему». Возможно ли теоретически изменить язык так, чтобы, если все параметры шаблона были по умолчанию, имя шаблона можно было использовать без параметров шаблона, чтобы одновременно означать шаблон и , который генерирует шаблон?

Возможно возможно . Но было бы сложно указать. Вам понадобится серьезный врач-специалист, который хорошо разбирается в грамматике C ++, чтобы точно знать, возможно ли это, и что именно нужно изменить, чтобы это сделать.

Но, в конце концов, это будет полезно только для небольшого, выбранного набора шаблонов: шаблонов, которые имеют значения по умолчанию для всех своих параметров. Реальный вопрос в том, является ли это достаточно распространенным случаем, чтобы стоить усилий.

2 голосов
/ 07 марта 2019

Я не считаю себя экспертом по языку, но моя позиция заключается в том, что проблема, которую пытается решить ваше предложение, решается намного проще, точно так же, как std::(basic_)string делает это.

У нас есть

template<
    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>
> class basic_string;

, а затем набор typedef с для "неопытных" пользователей, например std::string для std::basic_string<char>.

Если опытный пользователь хочет использоватьдругие параметры шаблона сами могут определять псевдоним типа, что хорошо и согласуется с вышесказанным.Более того, это четко отделяет шаблон от типов , которые создаются из него.

Ваше предложение разрешить шаблонам со значениями по умолчанию для всех параметров называться MyTemplate Один вместо того, чтобы требовать MyTemplate<> или использовать using MyTemplate = MyBasicTemplate<>;, имеет следующие проблемы:

  • Это усложняет грамматику и спецификацию языка.Вам нужно дотронуться до разрешенного синтаксиса всех контекстов, упомянутых в вашем вопросе, добавив возможность использовать имя шаблона там, где ожидается имя типа, но только , если соответствующий шаблонимеет значения по умолчанию для всех параметров шаблона.И если вы не измените их все, вы введете странное непоследовательное поведение.

  • Существует некоторое совпадение между вашим предложением и CTAD, но CTAD решительно относится к сокращению многословия типов для инициализации .CTAD предлагает значительный комфорт в своей области и расширяется с помощью руководств по выводам, в то время как синтаксический сахар вашего предложения актуален только в крошечной нише использования, с гораздо меньшими преимуществами.

  • Существует опасностьслучайно использовать неправильные параметры шаблона (вы имели в виду параметры шаблона по умолчанию или вы просто забыли указать те, которые вы хотели?).Даже если это не относится к вашему варианту использования, стандарт должен будет заняться этой потенциальной проблемой.

  • Существует также опасность вашего предложенияконфликтует с выводами руководств. Кто должен победить?

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

  • В целом, проблема, которую вы намереваетесь решить (сохранение создателей библиотеки a using или пользователей <> (или using), исключительно для шаблонов со всеми значениями по умолчанию), в лучшем случае незначительна и не будетдостаточная мотивация для существенного изменения нескольких основных аспектов языка.Это мой прогноз, по крайней мере.

...