Использование действительной функции-члена STATIC класса, который не может быть установлен - PullRequest
6 голосов
/ 02 ноября 2009

У меня есть следующий фрагмент кода:

Он компилируется без проблем под gcc-3.4, gcc-4.3, компилятором Intel, но не работает под MSVC9.

MSVC сообщает "использование неопределенного типа c_traits<C> при компиляции функции-члена шаблона класса void foo<C>::go(void) с C = short.

Дело в том, что компилятор пытается установить неиспользуемую функцию-член неиспользуемого класса, потому что этот класс просто не используется вообще.

Я могу обойти эту проблему, специализируя весь класс foo вместо того, чтобы специализироваться его функция-член. Но дело в том, что специализация всего класса немного проблематична для меня по разным причинам.

Большой вопрос: что правильно?

  • Мой код неверен, и компилятор gcc и intel просто игнорирует проблему, потому что они не устанавливают foo полностью, или
  • Код правильный, и это ошибка MSVC9 (VC 2008), которая пытается установить неиспользуемые функции-члены?

код:

class base_foo {
public:
    virtual void go() {};
    virtual ~base_foo() {}
};
template<typename C>
struct c_traits;

template<>
struct c_traits<int> {
    typedef unsigned int_type;
};

template<typename C>
class foo : public base_foo {
public:
    static base_foo *create()
    {
        return new foo<C>();
    }
    virtual void go() 
    {
        typedef typename c_traits<C>::int_type int_type;
        int_type i;
        i=1;
    }
};

template<>
base_foo *foo<short>::create()
{
    return new base_foo();
}

int main()
{
    base_foo *a;
    a=foo<short>::create(); delete a;
    a=foo<int>::create(); delete a;
}

Ответы [ 2 ]

3 голосов
/ 02 ноября 2009

Оба компилятора прямо здесь; поведение в вашем случае не определено. ISO C ++ 14.7.1 [temp.inst] / 9:

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

Причина этого довольно проста: виртуальной функции требуется запись vtable, и при виртуальной диспетчеризации может быть сложно определить, действительно ли данная виртуальная функция вызывается или нет. Таким образом, ISO C ++ позволяет компиляторам выполнять такой расширенный анализ для создания меньшего кода, но не требует его от них - поэтому, как программист C ++, вы всегда должны предполагать, что все виртуальные функции будут всегда создаваться. *

1 голос
/ 02 ноября 2009

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

Я подозреваю, что ваши конкретные ошибки компилятора звучат так, как будто вы вызваны только объявлением форварда

template<typename C>
struct c_traits;

Вы не полностью указали класс. Вы пробовали что-то простое, как:

template<typename C>
struct c_traits 
{
    // some default/dummy int type
};

Я подозреваю, что это по крайней мере остановит компилятор от жалоб.

EDIT

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

В этом случае создается экземпляр шаблона в виде:

 foo<short>

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

...