Странная ошибка компиляции (шаблоны)
От: LightGreen  
Дата: 25.10.12 07:25
Оценка:
При попытке скомпилировать следующий код Visual Studio Express 2005 выдаёт ошибку компиляции "unable to match function definition to an existing declaration". При этом GCC и даже Borland C++5.5 компилируют его без каких-либо проблем. С чем может быть связана эта ошибка и можно ли считать её ошибкой компилятора? Является ли этот код допустимым по стандарту языка?
template <class F>
class Container
{
public:
   class Iterator
   {
      friend class Container<F>;
      Iterator(int (&values)[F::Count]);
      int (&values_)[F::Count];
   };
   Iterator begin()
   {
      return Iterator(values_);
   }
private:
   int values_[F::Count];
};

template <class F>
Container<F>::Iterator::Iterator(int (&values)[F::Count]) : values_(values)
{}

class SomeF
{
public:
   static const int Count = 10;
};

int main(int argc, char *argv[])
{
   Container<SomeF> container;
}
Re: Странная ошибка компиляции (шаблоны)
От: PseudoSenior Украина  
Дата: 25.10.12 08:52
Оценка:
Привет. Стандарт не читал, не знаю. Но возможно чем-нибудь помогу.

Например, вот этот код скомпилируется думаю везде, хотя не знаю почему студия не компилит твой код(
она почему то считает что тип параметра который указан в объявлении не соответствует типу параметра, который используется в определении ) :

template <typename F>
class Container
{
public:
    class Iterator
    {
        typedef int (&MasInt) [F::Count];
        friend class Container<F>;
        Iterator(MasInt);
        MasInt values_;
    };
    Iterator begin()
    {
        return Iterator(values_);
    }
private:
    int values_[F::Count];
};

template <typename F>
Container<F>::Iterator::Iterator(MasInt values) : values_(values)
{
}

class SomeF
{
public:
    static const int Count = 10;
};
Re: Странная ошибка компиляции (шаблоны)
От: rg45 СССР  
Дата: 25.10.12 09:57
Оценка:
Здравствуйте, LightGreen, Вы писали:

LG>При попытке скомпилировать следующий код Visual Studio Express 2005 выдаёт ошибку компиляции "unable to match function definition to an existing declaration". При этом GCC и даже Borland C++5.5 компилируют его без каких-либо проблем. С чем может быть связана эта ошибка и можно ли считать её ошибкой компилятора? Является ли этот код допустимым по стандарту языка?

LG>[snipped]

Неужели так трудно хоть чуть-чуть минимизировать пример? Проблема ведь воспроизводится гораздо меньшим количеством строк:
template <typename T>
struct A
{
   void foo(int (&values)[T::Count]);
};

template <typename T>
void A<T>::foo(int (&values)[T::Count]) //error C2244: 'A<T>::foo' : unable to match function definition to an existing declaration
{
}


Не берусь судить, насколько такое поведение соответствует (или наоборот, не соответствует) стандарту, но о причине ошибки догадаться не трудно: у компилятора в первой фазе просто нет информации о том, что T::Count имеет целочисленный тип, соответственно, он не может прийти к выводу о том, что декларатор int (&values)[T::Count] обозначает ссылку на массив. Если немного ему помочь, все приходит в порядок:
template <typename T>
struct A
{
   static const int Count = T::Count;
   void foo(int (&values)[Count]);
};

template <typename T>
void A<T>::foo(int (&values)[Count])
{
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Странная ошибка компиляции (шаблоны)
От: LightGreen  
Дата: 25.10.12 10:06
Оценка:
Здравствуйте, rg45, Вы писали:

R>Неужели так трудно хоть чуть-чуть минимизировать пример? Проблема ведь воспроизводится гораздо меньшим количеством строк:

Чуть-чуть уже минимизировано — убрано 95% кода. Вы убрали ещё несколько процентов, честь Вам и хвала.

R>Не берусь судить, насколько такое поведение соответствует (или наоборот, не соответствует) стандарту, но о причине ошибки догадаться не трудно: у компилятора в первой фазе просто нет информации о том, что T::Count имеет целочисленный тип, соответственно, он не может прийти к выводу о том, что декларатор int (&values)[T::Count] обозначает ссылку на массив. Если немного ему помочь, все приходит в порядок:


Спасибо за объяснение! Но почему тогда другие компиляторы, тот же GCC или древний Borland, спокойно этот код компилируют? У них в первой фазе есть вся информация??
Re[2]: Странная ошибка компиляции (шаблоны)
От: LightGreen  
Дата: 25.10.12 10:08
Оценка:
Спасибо за предложенное решение! Я поступил несколько иначе: заменил обычный массив [] на std::vector и всё скомпилировалось.
Re[3]: Странная ошибка компиляции (шаблоны)
От: rg45 СССР  
Дата: 25.10.12 10:15
Оценка:
Здравствуйте, LightGreen, Вы писали:

LG>Спасибо за объяснение! Но почему тогда другие компиляторы, тот же GCC или древний Borland, спокойно этот код компилируют? У них в первой фазе есть вся информация??


Сходу не берусь объяснить, тут нужно время, чтоб внимательно посмотреть стандарт. Может, кто-то из знатоков объяснит.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Странная ошибка компиляции (шаблоны)
От: PseudoSenior Украина  
Дата: 25.10.12 10:18
Оценка:
R>Не берусь судить, насколько такое поведение соответствует (или наоборот, не соответствует) стандарту, но о причине ошибки догадаться не трудно: у компилятора в первой фазе просто нет информации о том, что T::Count имеет целочисленный тип, соответственно, он не может прийти к выводу о том, что декларатор int (&values)[T::Count] обозначает ссылку на массив. Если немного ему помочь, все приходит в порядок:
R>
R>template <typename T>
R>struct A
R>{
R>   static const int Count = T::Count;
R>   void foo(int (&values)[Count]);
R>};

R>template <typename T>
R>void A<T>::foo(int (&values)[Count])
R>{
R>}
R>


если бы так было, то не компилировался бы следущий код

template <typename T>
struct A
{
void foo(int (&values)[T::Count])
{
}
};
Re[3]: Странная ошибка компиляции (шаблоны)
От: rg45 СССР  
Дата: 25.10.12 10:43
Оценка:
Здравствуйте, PseudoSenior, Вы писали:


R>>Не берусь судить, насколько такое поведение соответствует (или наоборот, не соответствует) стандарту, но о причине ошибки догадаться не трудно: у компилятора в первой фазе просто нет информации о том, что T::Count имеет целочисленный тип, соответственно, он не может прийти к выводу о том, что декларатор int (&values)[T::Count] обозначает ссылку на массив. Если немного ему помочь, все приходит в порядок:

R>>[...]

PS>если бы так было, то не компилировался бы следущий код


PS>template <typename T>

PS>struct A
PS>{
PS> void foo(int (&values)[T::Count])
PS> {
PS> }
PS>};

Я думаю, что это таки ошибка компилятора, которая проявляется при определенных условиях.
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.