Законно ли в C ++ передавать адрес статического const int без определения в шаблон? - PullRequest
2 голосов
/ 11 августа 2009

Мне трудно решить, должен ли этот код компилироваться, или если только у обоих компиляторов, которые я пробовал, есть ошибка (GCC 4.2 и Sun Studio 12).В общем, если у вас есть статический член класса, который вы объявляете в заголовочном файле, вы должны определить его в некотором исходном файле.Однако в стандарте сделано исключение для статических константных интегралов.Например, это разрешено:

#include <iostream>

struct A {
    static const int x = 42;
};

Без необходимости где-либо добавлять определение x вне тела класса.Я пытаюсь сделать то же самое, но я также беру адрес x и передаю его шаблону.Это приводит к ошибке компоновщика с жалобой на отсутствие определения.Приведенный ниже пример не связывает (отсутствует определение для A :: x), даже если он находится в одном и том же исходном файле:

#include <iostream>

template<const int* y>
struct B {
    static void foo() { std::cout << "y: " << y << std::endl; }
};

struct A {
    static const int x = 42;
    typedef B<&x> fooness;
};

int main()
{
    std::cout << A::x << std::endl;
    A::fooness::foo();
}

Что странно, поскольку работает, пока я не передаюадрес к шаблону.Это ошибка или как-то технически совместимая со стандартами?

Редактировать: Я должен указать, что & A :: x является , а не значением времени выполнения.Память выделяется для статически распределенных переменных во время компиляции.

Ответы [ 4 ]

6 голосов
/ 11 августа 2009

Для того, чтобы быть правильно сформированной программой, вы должны иметь определение статической переменной (без инициализатора в данном случае), если она действительно используется, и принимать адрес как использование:

  • Стандарт C ++ 2003: 9.4.2 Элементы статических данных Пункт 4 (жирный шрифт)

Если член статических данных имеет постоянную целочисленный или константный тип перечисления, его объявление в классе определение может указать инициализатор констант, который должен быть интегральное постоянное выражение (5.19). В этом случае член может появиться в интегральные константные выражения. The член по-прежнему должен быть определен в Область пространства имен, если она используется в программа и область имен определение не должно содержать инициализатор

1 голос
/ 11 августа 2009

Вы пытаетесь передать значение времени выполнения в шаблон, это невозможно. Единственными допустимыми параметрами шаблона являются типы (class / typename) или целочисленные значения констант (int / bool / etc).

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

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

Адрес статического const не является значением времени выполнения и может быть полностью разрешен во время соединения.

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

Интересно, что он отлично скомпилирован для меня на VS 2008. Я предположил, что ошибка произошла от typedef, потому что во время компиляции, когда он пытается скомпилировать 'B' с & x в качестве типа шаблона, он не знает, где адрес х будет. Тем не менее ... он компилируется и дает разумный вывод.

...