Ошибка компилятора VS2008 (+?) С шаблонными функциями и «использованием пространства имен» - PullRequest
5 голосов
/ 14 сентября 2010

Я обнаружил, что этот странный случай с некоторым кодом (ниже) не компилируется в Visual Studio 2008 и выдает «ошибку C2872:« Неоднозначность »: неоднозначный символ» в строке 12.

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

То же самоекод компилируется в GCC.

Кажется, что оба компилятора генерируют код для TemplatedFunction после определения using namespace Namespace, по крайней мере, насколько я могу судить, вводя ошибки и просматривая порядок их вывода.

namespace Ambiguity
{
    class cSomeClass
    {
    };

    template<class T>
    void TemplatedFunction(T a)
    {
        // this is where the error occurs, the compiler thinks Ambiguity
        // might refer to the class in RequiredNamespace below
        Ambiguity::cSomeClass(); 
    }
}

namespace RequiredNamespace 
{
    // without a namespace around this class, the Ambiguity class 
    // and namespace collide
    class Ambiguity
    {
    };
}

int main()
{
    // to force the templated function to be generated
    Ambiguity::TemplatedFunction(4); 
}

// removing this removes the error, but it shouldn't really do anything
using namespace RequiredNamespace; 

Очевидно, что это изготовленный пример, но оригинал извлечен из реального случая, когда using namespace находится в автоматически сгенерированном файле, созданном с помощью стороннего кода.

Isэто ошибка в компиляторе?

Ответы [ 2 ]

5 голосов
/ 14 сентября 2010

Я согласен, что это ошибка, но некоторое понимание того, что происходит, можно получить, сгенерировав список сборок, соответствующий вашему файлу (используйте параметр / Fa файла cl.exe).

Итак, закомментируйте объявление using, сгенерируйте файл .asm и откройте его в текстовом редакторе.Просканируйте файл, и вы увидите, что экземпляр шаблона находится внизу файла (он начинается с ??$TemplatedFunction@H@Ambiguity@@YAXH@Z PROC) и находится под сборкой, созданной для основной функции (начинается с _main PROC).В сообщении об ошибке говорится «см. Ссылку на создание экземпляра шаблона функции», поэтому оно ссылается на создание экземпляра функции шаблона, и в листе сборки ясно, что это создание находится внизу файла.

Теперь отредактируйтекод для замены функции шаблона на NonTemplatedFunction(int a) и компиляции, генерируя листинг сборки.Просмотрите список сборок, и вы увидите, что код сборки, сгенерированный для NonTemplatedFunction(int a), отображается выше _main PROC.

Что означает эта болтовня?Когда компилятор Visual Studio 2008 превращает ваши шаблоны в реальный код, он фактически добавляет некоторый код в конец вашего файла после объявления об использовании.Ваше объявление об использовании означает, что имена в автоматически сгенерированном коде «неоднозначны».Процесс, который gcc использует для создания экземпляров шаблонов, очевидно, позволяет избежать этой проблемы.

2 голосов
/ 14 сентября 2010

Я считаю, что это ошибка, согласно 7.3.4, пункт 1 стандарта C ++ 03:

Директива using указывает, что имена в назначенном пространстве имен могут использоваться в области действияв котором директива using появляется после директивы using.

Таким образом, объявление конца файла не должно иметь никакого эффекта.

...