2016-04-27 3 views
5

Я унаследовал ужасный бит устаревшего кода, который включает около 1000 строк определения класса полезности, которые должны появиться перед «настоящим» кодом в исходном файле. Для того, чтобы избежать столкновений с другими модулями, которые также могли бы связанные унаследованные классы, я поставил служебный класс в безымянное пространство имен:Есть ли только одно неназванное пространство имен для единицы компиляции?

namespace { 
    class OldUtils { 
     OldUtils(); 
     int foo(); 
     double bar(); 
    }; 

    OldUtils::OldUtils() { 
     // hundreds of lines 
    } 

    int OldUtils::foo() { 
     // hundreds more lines 
    } 

    ... 
} 

class ActuallyInteresting { 
    // uses OldUtils 
}; 

Но я предпочел бы иметь ActuallyInteresting код, который люди будут (на самом деле), заинтересованными в в верхней части файла, например начиная с строки 50, чем справа внизу, например. начиная с строки 1000. Разделение классной утилиты horrid на отдельный блок компиляции не является вариантом, по причинам более высокого уровня я не буду вдаваться!

Так что мне интересно, можно ли положить короткое объявление класса - без определения метода - в неназванное пространство имен в верхней части файла и более длинные определения методов в другом безымянном пространстве имен внизу:

namespace { 
    class OldUtils { 
     OldUtils(); 
     int foo(); 
     double bar(); 
    }; 
} 

class ActuallyInteresting { 
    // uses OldUtils 
}; 

namespace { 
    OldUtils::OldUtils() { 
     // hundreds of lines 
    } 

    int OldUtils::foo() { 
     // hundreds more lines 
    } 

    ... 
} 

будут ли эти два «отдельные» безымянные пространства имен можно рассматривать как тот же объем в пределах единицы компиляции, или будет генерироваться различные уникальные пространства имен для каждого? Есть ли в стандарте что-нибудь об этом?

+0

Каждый неназванных имен будет уникальным для каждой единицы перевода (так же, как статический в ЕП) –

+0

@ DieterLücking: Если это так, то как же доступ к глобальной переменной в безымянном пространстве имен в другом ЕП? Добавляется ли название другой единицы перевода в текст разрешения области? –

ответ

4

Будет ли эти два «отдельные» безымянные пространства имен можно рассматривать как же объема в пределах единицы компиляции, или различные уникальные пространства имен генерироваться для каждого? Есть ли в стандарте что-нибудь о ?

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

Цитируя latest standard draft ... (курсив мой)

$7.3.1.1 Неназванного-пространство имен определение ведет себя, как если бы оно было заменено

inlineopt namespace unique { /* empty body */ } 
using namespace unique ; 
namespace unique { namespace-body } 

где появляется inline тогда и только тогда, когда он появляется в неназванных-пространство имен определения и всех вхожденияuniqueв блоке с перевода заменяется одним и тем же идентификатором, и это идентификатора отличается от всех других идентификаторов в ЕПЕ

компилировать эту короткую программу, компилятор должен жаловаться переменным переопределение ...

namespace { int c = 0; } 
namespace { double c = 8; } 

int main(){ ++c; } 

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

namespace { int c = 0; } 
namespace { void f(){ c = 8; } } 

int main(){ ++c; } 
-2

Вы можете выяснить ответ самостоятельно, просто проверяя, если следующий код компилируется:

namespace { 
    int a; 
} 

namespace { 
    int *b=&a; 
} 

Вы ожидаете получить ошибку компиляции, если каждое пространство имен является уникальным; и это будет скомпилировано без проблем, если неназванное пространство имен является одним и тем же, в обоих случаях.

+0

Должен был сказать, что я сделал базовый тест в этом ключе (он и это действительно работает). Но гарантируется ли это стандартом или не зависящим от компилятора неопределенным поведением? Спасибо – andybuckley

+2

Просто использование компилятора не делает код стандартным. MSVS с удовольствием скомпилирует 'int & var = some_function_that _retunrs_int()', который не является стандартным. – NathanOliver

Смежные вопросы