Почему GCC не находит мою не шаблонную функцию? («Нет подходящей функции для вызова ...») - PullRequest
0 голосов
/ 10 апреля 2009

В MSVC 2008 у меня есть следующий код:

class Foo {
  //  Be a little smarter about deriving the vertex type, to save the user some typing.
  template<typename Vertex> inline void drawVertices(
    Elements vCount, RenPrim primitiveType, PixMaterial *mtl, Vertex const *vertices)
  {
    this->drawVertices(vCount, primitiveType, mtl, vertices, Vertex::VertexType);
  }

  virtual void drawVertices(
    Elements vCount,
    RenPrim primitiveType,
    PixMaterial *mtl,
    void const *vertices,
    uint vertexType) = 0;
};

Я использую что-то вроде:

struct RenFlexibleVertexPc
{
  enum { VertexType = RenVbufVertexComponentsPc };
  float x;
  float y;
  float z;
  GraVideoRgba8 c; // Video format, not external!
};


  PixMaterial *material;
  struct Pc : RenFlexibleVertexPc
          {
            void set(Triple t, uint cl) { x = (float)t.x_; y = (float)t.y_; z = (float)t.z_; c = cl; }
          } vpc[4];
  ...
  Foo *renderer;
  renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);

Это прекрасно работает в MSVC 2008 SP1. Тем не менее, GCC (3.4 и 4.1,2) выдает ошибку «не соответствует функция для вызова функции», очевидно, не видя шаблон, когда есть функция не шаблонная с большим количеством аргументов.

Не работает ли GCC или мой код, и если да, то почему?

Ответы [ 3 ]

1 голос
/ 14 апреля 2009

Нет проблем с перегрузкой или наследованием:

#include <iostream>
#include <memory>

namespace {
    struct A {
        virtual void f()
        {
            std::cout<<"inside A's f()\n";
        }

        template <typename T> void f(T t)
        {
            std::cout<<T::i<<'\t';
            this->f();
        }
    };

    struct B : A {
        void f()
        {
            std::cout<<"hello\t";
            A::f();
        }
    };

    struct C {
        static const unsigned int i = 5;
    };

    struct D {
        enum { i = 6 };
    };
}

int main()
{
    std::auto_ptr<A> b(new B());
    b->f(C());
    b->f(D());
}

Работает правильно. С другой стороны, самый маленький пример, который я могу найти, который показывает вашу проблему, не имеет наследования или перегрузки:

#include <iostream>

namespace {
    struct A {
        template<class C> void print(C c)
        {
            c.print();
        }
    };
}

int main()
{
    struct B {
        void print()
        {
            std::cout << "whee!\n";
        }
    };

    A a;
    B b;
    a.print(b);
}

Обратите внимание: если struct B определено в пространстве имен (будь то безымянное пространство имен, или совершенно другое пространство имен, или глобальное пространство имен) вместо main(), то это компилируется без ошибок.

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


А вот ваш ответ от разработчиков GCC (по ссылке выше): «Локальные классы не могут быть аргументами шаблона».

Итак, код не работает. Не то чтобы это плохая идея . Фактически C ++ 0x снимает это ограничение.

Я заметил линию

Обратите внимание, что код работает в GCC, если я явно приведу vpc к (RenF FlexibleVertexPc *)

И поскольку RenFlexibleVertexPc не является локальным классом, это имеет смысл. Однако Pc является локальным классом / структурой, поэтому он не разрешен.

1 голос
/ 15 апреля 2009

@ OP: Указание параметра шаблона является допустимым подходом.

renderer->drawVertices<RenFlexibleVertexPc>(4, RenPrimTriangleFan, material, vpc);

Благодаря дополнениям Пита ваш код также компилируется в Apple GCC 4.0.1, поэтому я подозреваю, что в опубликованном вами коде чего-то не хватает, что вызывает проблему.

@ Макс. GCC обрабатывает ваш источник стандартно. Структура B является локальной для main (), поэтому B (и, следовательно, main () :: B :: print ()) не видна вне main (). Как вы, наверное, знаете, переместите определение B за пределы main (), и оно скомпилируется.

0 голосов
/ 10 апреля 2009

Определение VertexType уже есть в коде (перечисление). Элементы без знака долго. Обратите внимание, что код работает в GCC, если я явно приведу vpc к (RenFlexibleVertexPc *)

Если это перечисление, зачем передавать объект типа массив 4 структуры? Что такое RenFlexibleVertexPc? Последний аргумент drawVertices должен быть либо постоянным указателем на объект Vertex, либо const* на объект класса, производного от Vertex.

Foo *renderer;
renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);

Вы вызываете функцию по неинициализированному указателю. Я надеюсь, что это не настоящий код. \

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