Беда с шаблонами и __LINE__ - PullRequest
3 голосов
/ 09 ноября 2010

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

Обновление:
Код ниже взят из msdn, это не то, что я пытаюсь сделать. То, что я пытаюсь сделать, это использовать шаблон, чтобы иметь уникальный тип каждый раз, когда пользователь создает его с помощью макроса. Таким образом, можно выполнить проверку времени компиляции, чтобы типы не смешивались. Я работаю над кодом из этой статьи: http://www.artima.com/cppsource/safelabels.html и да, я знаю о существовании std :: bitset спасибо.

Как отметил Тони, __LINE__ в любом случае не является сильной гарантией уникальности.

Я сталкиваюсь со следующей ошибкой:

http://msdn.microsoft.com/en-us/library/kyf0z2ka%28v=VS.100%29.aspx

C2975 will also occur when you use `__LINE__` as a compile-time constant with /ZI:

// C2975b.cpp
// compile with: /ZI
// processor: x86
template<long line> 
void test(void) {}

int main() {
    test<__LINE__>();   // C2975
    test<__LINE__>();   // OK
}

Компиляция без / ZI - это хорошо, но в msvc это по умолчанию, и я не предполагаю, чтобы все пользователи моей библиотеки сначала сталкивались с ошибками компилятора, пока я не скажу им отключить этот ключ.

Как бы вы решили эту проблему?

Единственная реалистичная идея, которую я имею до сих пор, это проверка наличия msvc, а затем использование __COUNTER__ для msvc ...

Обновление:
На самом деле __COUNTER__ не работает, потому что мне нужно, чтобы типы были уникальными при каждом объявлении, но для разных единиц перевода они должны быть одинаковыми, в противном случае я получаю проблемы компоновщика из неразрешенных внешних ссылок.

1 Ответ

3 голосов
/ 09 ноября 2010

Первая задача для получения уникальных экземпляров состоит в том, чтобы различать единицы перевода.К счастью, этот бит прост:

namespace { struct unique_type {}; }
template<typename T> int foo() { return 42; }
static int bar = foo<unique_type>();

Это может быть помещено в заголовок и будет создавать различные foo<unique_type>() в каждом модуле перевода.Добавление __LINE__ требует небольшой работы из-за ошибки MSVC:

namespace {
    struct unique_type{};
    const int LINE = __LINE__;
}
template<typename T, int N> int foo() { return 42; }
static int bar = foo<unique_type, LINE>();
...