Странное поведение аргументов шаблона в Visual C ++? - PullRequest
1 голос
/ 25 августа 2009

Я попробовал этот пример из «Шаблон C ++ - Полное руководство» Николая М. Йосуттиса

#include <iostream>

using namespace std;

template< typename T >
class List {
};

typedef enum { RED, GREEN, BLUE } *color_ptr;

int main() {
    struct Local {
        int x;
    };

    List< Local > l; // error : local type in template argument
    List< color_ptr > l1; // error : unamed type in template argument.

    return 0;
}

С g ++ под Ubuntu 9.04 я получил ошибки компилятора. Однако этот фрагмент кода был успешно скомпилирован в Visual C ++ 2008. И, как я читал из книги: «Аргументы типа шаблона - это« значения », указанные для параметров типа шаблона. Наиболее часто используемые типы могут использоваться в качестве аргументов шаблона, но есть два исключения: 1. Локальные классы и перечисления (другими словами, типы, объявленные в определении функции) не могут быть включены в аргументы типа шаблона. 2. Типы, которые включают в себя безымянные типы классов или безымянные типы перечисления, не могут быть аргументами шаблонного типа (безымянные классы или перечисления, которым дано имя посредством объявления typedef, в порядке.) Так есть ли ошибка в Visual C ++?

Ответы [ 3 ]

3 голосов
/ 25 августа 2009

Есть много других случаев, когда вы обнаруживаете, что эта книга отличается от поведения VC ++. Примерами являются инструменты неоднозначности typename и template и привязка неконстантных ссылок к значениям.

В этом случае, конечно, поведение G ++ правильное, как говорится в книге. Попробуйте следующие изменения

typedef enum color_type { RED, GREEN, BLUE } *color_ptr;

template< typename T >
class List {
};

// not really local anymore :)
struct Local { int x; };
int main() {
  List< Local > l;
  List< color_type > l1;
}

Следующий стандарт C ++ (C ++ 0x) допускает локальные типы в качестве аргументов шаблона.


Обратите внимание, что означает книга с присвоением имени типу с помощью typedef. Это не относится к следующему, поскольку имя A не называет тип перечисления, а указывает на него тип указателя.

typedef enum { X } *A;

Итак, когда вы используете A или в своем примере color_ptr, вы не будете в безопасности. Технически это имя является типом указателя на тип без связи, что не допускается в качестве аргумента шаблона.


Обратите внимание, что вы можете поместить Local в безымянное пространство имен, чтобы сделать тип локальным для текущей единицы перевода, но при этом иметь тип, приемлемый в качестве аргумента шаблона типа. Таким образом, если вы просто хотите иметь тип «нуля» для чего-то вроде функционального объекта, структура не будет конфликтовать со структурой, определенной в другом файле.

namespace {
  // not really local anymore, but "translation unit local" :)
  struct Local { int x; };
}
1 голос
/ 25 августа 2009

Это допустимые расширения стандарта со стороны MSVC. MS делает достойную работу, документируя параметры своего компилятора , соответствие или отклонение от стандартов, & c; в частности, как задокументировано здесь , /Za скажет компилятору пометить как ошибки отклонения от стандарта (который он специфически называет «ansi C ++» вместо ISO; -).

0 голосов
/ 25 августа 2009

Проверьте, если вы компилируете с расширениями Microsoft (/Ze).

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