Экземпляр не шаблонного класса, использующего шаблонный конструктор, интерпретируемый как определение функции? - PullRequest
3 голосов
/ 23 октября 2011

Моя проблема лучше всего демонстрируется следующим кодом:

#include <fstream>
#include <iterator>

class Bar
{
    public: template <class Iterator> Bar(Iterator first, Iterator last) {}
};

void foo(const Bar& bar) { }

int main(int argc, char** argv)
{
    std::ifstream file("file.txt");

    Bar bar(std::istream_iterator<char>(file), std::istream_iterator<char>());

    foo(bar); // error C2664: 'foo' : cannot convert parameter 1 from 'Bar (__cdecl *)(std::istream_iterator<_Ty>,std::istream_iterator<_Ty> (__cdecl *)(void))' to 'const Bar &'
              // with
              // [
              //     _Ty=char
              // ]
              // Reason: cannot convert from 'overloaded-function' to 'const Bar'
              // No constructor could take the source type, or constructor overload resolution was ambiguous

    return 0;
};

Вот несколько подобных примеров bar, которые не вызывают такой же неоднозначности:

Bar bar = Bar(std::istream_iterator<char>(file), std::istream_iterator<char>());

и

std::istream_iterator<char> start(file);
std::istream_iterator<char> end;
Bar bar(start, end);

У меня вопрос , что это за первое объявление bar, которое приводит к неправильной интерпретации?

примечание: я тестирую сVisual Studio 2010 (10.0.30319.1)

Ответы [ 2 ]

2 голосов
/ 23 октября 2011

ArunMu получает частичный кредит, это действительно пример Most Vexing Parse , но этот термин был придуман в Effective STL Мейера (глава 1, пункт 6), а не в исключительном C ++.

Это - это , интерпретируемый как указатель на функцию (часть ошибки (__cdecl *) является ошибкой), и, очевидно, стандарт C ++ требует, чтобы она интерпретировалась таким образом. Есть ли у кого-нибудь цитата из этой главы / стиха?

Существует также другое решение для устранения неоднозначности. Добавление дополнительного набора скобок вокруг каждого параметра тоже работает:

Bar bar( (std::istream_iterator<char>(file)), (std::istream_iterator<char>()) );

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

2 голосов
/ 23 октября 2011

Я думаю, что это связано с «самым неприятным синтаксическим анализом C ++», который вы найдете в книге «Эффективный STL» Майера.

 Bar bar(std::istream_iterator&lt char &gt(file), std::istream_iterator &lt char &gt()); 
Рассматривается как объявление функции **.

из-за чего в foo(bar); вместо этого вы отправляете указатель на функцию :)

Выполнение, как показано ниже, не будет иметь ошибки: Bar bar = Bar(//your arguments here); foo(bar);

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