Nano Hash - криптовалюты, майнинг, программирование

Шаблон в шаблоне: почему «››» должен быть «› ›» в списке аргументов вложенного шаблона

Я знаю, что когда мы используем шаблон внутри другого шаблона, мы должны написать это так:

vector<pair<int,int> > s;

и если мы напишем это без пробела:

vector<pair<int,int>> s;

мы получим ошибку:

`>>' должно быть `> >' во вложенном списке аргументов шаблона

Я вижу, это понятно, но я просто не могу не задаться вопросом, в каких случаях это будет действительно двусмысленно?



Ответы:


1

Иногда вы хотите, чтобы это было >>. Рассмотреть возможность

boost::array<int, 1024>>2> x;

В С++ 03 это успешно анализирует и создает массив размером 256.

14.07.2011
  • Но вы можете устранить неоднозначность и в C++0x: boost::array<int, (1024>>2)> x; 14.07.2011
  • @Армен действительно можешь. Но это один из случаев, когда это неоднозначно, так как программа действительна, когда интерпретируется как значение C++03. 14.07.2011
  • Это действительно очень интересно. Но, тем не менее, это не двусмысленно, поскольку единственная интерпретация ››, которая может привести к правильному построению, – это ›› как сдвиг. Если вы рассматриваете его как два закрывающих ›, это недействительно. Есть ли на самом деле пример, в котором обе интерпретации дали бы правильные конструкции? 14.07.2011
  • @Армен правильно. Я интерпретировал неоднозначно не так, как можно было бы ожидать, поэтому я поставил его в ''es. Спрашивающий, кажется, спросил, в каком случае имеет смысл трактовать его как ››?. Есть действительно неоднозначные случаи (недавно один тестовый пример был показан в способах возврата true на C++0x и false на C++03, и IIRC, один тестовый пример показан в документе, предлагающем изменение угловых скобок для C+ +0x). 14.07.2011
  • Я тоже об этом думал... Логично. Что делает мой ответ неверным, а ваш правильным. Но удалять не буду. +1 :) 14.07.2011
  • Ни один здравомыслящий человек не хочет этого. Даже если вы сумасшедший, вы должны предпочесть boost::array<int, (1024>>2)> x;, что устраняет двусмысленность. Кроме того, даже без этого его следует интерпретировать как array‹int, (1024 ›› 2)› x; имеет смысл и массив ‹int, 1024› (2› x); можно проверить как глупый случай, которого не должно быть ни в одной программе. Я НЕ ХОЧУ ВСТАВЛЯТЬ ДОПОЛНИТЕЛЬНЫЕ ПРОБЕЛЫ В МОИ ШАБЛОНЫ, ЭТО ПРИЧИНЯЕТ НЕСООТВЕТСТВУЮЩИЙ КОД. 03.09.2016
  • Этот фрагмент кода также создает массив размером 256 с g++ -std=c++98 в моем тесте. 06.03.2017
  • следующее потенциально действительно? ( (templated::thing<int, 1024>)>2)> x; Если да, то это может быть правильной интерпретацией данного примера. 18.10.2018
  • @bean boost::array — это шаблон типа, поэтому это недопустимая интерпретация для моего примера. 21.10.2018
  • @Johannes, как насчет того, чтобы игнорировать тот факт, что boost::array - это что-то, и просто учитывать сам данный синтаксис? (вот почему вместо этого я написал templated::thing.) То есть, может ли быть templated::thing, где ( (templated::thing<int, 1024>)>2)> x; является допустимым синтаксисом? Я просто задаюсь вопросом, является ли ›› как сдвиг единственно допустимой интерпретацией данного синтаксиса. 21.10.2018
  • @bean, ставите ли вы круглые скобки, очень важно, потому что он разбивается ›› на две лексемы. Итак, если вещь является шаблоном функции, ваш примерный код имеет допустимый синтаксис. И если есть соответствующим образом перегруженный operator>, он может даже скомпилироваться. Но я не вижу отношения к моему примеру. 21.10.2018
  • @JohannesSchaub-litb Суть исходного вопроса заключается исключительно в синтаксисе и двусмысленности в отношении интерпретации компилятором одинарного или двойного токена ››. Таким образом (игнорируя тот факт, что boost::array на самом деле является вещью, в которой данное добавление круглых скобок не имеет смысла), я указывал, что может быть альтернативная токенизация вашего данного примера, где необработанный синтаксис потенциально может быть действительным (только синтаксис), в отличие от комментария выше, в котором предполагается, что единственной допустимой интерпретацией вашего примера является предполагаемая. 23.10.2018

  • 2

    Это никогда не будет двусмысленным. Это подтверждается тем фактом, что в C++0x вам больше не нужно писать пробел между закрывающими шаблонами >.

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

    14.07.2011
  • Спасибо! Хотя я использую компилятор C++0x каждый день (не для этого кода), я действительно мало о нем знаю. Спасибо за совет:) 14.07.2011
  • @Ziyao Wei: Пожалуйста, но вы действительно должны принять ответ @Johannes, потому что мой просто неверен :) 14.07.2011

  • 3

    В текущем стандарте токенизация является жадной, поэтому >> будет обрабатываться как одиночный токен, точно так же, как a +++ b будет анализироваться как a ++ + b. Это изменил и новый стандарт. Хотя это требует дополнительной работы от разработчиков компилятора, было сочтено, что в целом оно того стоит (и в любом случае некоторые крупные компиляторы уже реализуют это как расширение).

    14.07.2011

    4

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

    Исторический оператор ">>" является оператором. Он «идентифицируется», так как исходный файл разбит на токены. Затем эти токены «понимаются» в некотором контексте во время грамматического анализа (спустя долгое время после завершения токенизации).

    Если вы выполнили грамматический анализ во время токенизации, то у вас есть «подсказки», помогающие различать, что «>>» следует рассматривать как два замыкания объявления (или определения) шаблона. Тем не менее, исторически исторические компиляторы C++ работают иначе. (Новые компиляторы делают больше обратной связи между грамматическим анализом и токенизацией, включая больше «упреждающих действий», чтобы помочь разрешить эти неоднозначности.)

    Да, новый стандарт С++ 0x меняет это и заставляет поставщиков компиляторов переписывать свои реализации, чтобы устранить неоднозначность «>>» в вашем случае. Таким образом, это никогда не будет двусмысленным в будущем. Однако старые компиляторы C++ не могут с этим справиться, поэтому на данный момент можно считать "хорошей практикой" поддерживать совместимость вашего кода с пробелом между символами '>'.

    14.07.2011

    5

    Чтобы избежать этой ошибки, установите соответствующий диалект C++. Например, с gcc 4.9 следующий файл не компилируется с g++:

    #include <vector>
    #include <utility>
    
    int main()
    {
        using namespace std;
        vector<pair<int, int>> v; // compile error!
        return 0;
    }
    

    Перейдем к сути вещей:

    #include <iostream>
    
    int main()
    {
        std::cout << __cplusplus << std::endl;
        return 0;
    }
    

    Скомпилированный всего с g++ test.cpp этот код выводит 199711. Хотя gcc 4.9 был выпущен в 2014 году, диалектом C++ по умолчанию является C++98 с расширениями GNU. C++98 требует, чтобы мы написали vector<pair<int, int> >. Если вам больше нравится vector<pair<int, int>>, компилируйте с -std=c++11 или -std=gnu++11.

    19.07.2015

    6

    Это зависит от компилятора. Visual Studio не требует этого, т.е. оба работают, в то время как g++ выдает ошибку. Я думаю, что это зависит от реализации компилятора.

    14.07.2011

    7

    Синтаксис потока

    cin >> var;

    Vs

    Синтаксис вложенного шаблона

    For<Bar<Barz>>

    Первая фаза компилятора, лексический анализатор не сможет распознать.

    22.06.2019

    8

    У меня была эта проблема с программированием класса на С++, и я решил ее, выполнив следующие действия:

    Строка, вызвавшая ту же ошибку, упомянутую здесь ранее:

    findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector<std::vector<cv::Point»&);
    

    Строка, прошедшая через кросс-компилятор GCC и сработавшая:

    findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector< std::vector<cv::Point> >&);
    

    Для меня это была просто ошибка в интерпретации высказывания.

    16.09.2016
    Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..