Static const в классе С++: undefined ссылка

У меня есть класс для локального использования (т.е. его совпадение - это только файл С++, в котором он определен)

class A {
public:
    static const int MY_CONST = 5;
};

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: 
                                            // undefined reference to `A::MY_CONST` 
}

Весь код находится в том же файле С++. При компиляции с использованием VS на окнах проблем нет.
Однако при компиляции в Linux я получаю ошибку undefined reference только для второго оператора.

Любые предложения?

Ответ 1

std::min<int> аргументы равны const int& (а не только int), то есть ссылки на int. И вы не можете передать ссылку на A::MY_CONST, потому что она не определена (только объявлена).

Укажите определение в файле .cpp вне класса:

class A {
public:
    static const int MY_CONST = 5; // declaration
};

const int A::MY_CONST; // definition (no value needed)

Ответ 2

// initialize static constants outside the class

class A {
public:
    static const int MY_CONST;
};

const int A::MY_CONST = 5;

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: 
                                            // undefined reference to `A::MY_CONST` 
}

Ответ 3

Чтобы объяснить, что происходит здесь:

Вы объявили static const integer внутри класса, эта "функция" здесь, чтобы иметь возможность использовать его как постоянное выражение, т.е. для локального размера массива, несимметричных параметров шаблона и т.д. Если компилятор хочет использовать это константное выражение, он должен уметь видеть это значение в этой единицы перевода.

9,5/3

Если постоянный элемент статистических данных со стабилизатором константы является интегральным или перечисляемым, его объявление в классе определение может указывать логический или равный-инициализатор, в котором каждое предложение-инициализатор, являющееся выражением присваивания, является постоянным выражением (5.19). Статический член данных типа literal может быть объявлен в определение класса со спецификацией constexpr; если это так, в его декларации указывается логический или равный-инициализатор в котором каждое предложение-инициализатор, являющееся выражением-присваиванием, является постоянным выражением. [Примечание: В обоих эти случаи, член может появляться в постоянных выражениях. - end note] Участник должен быть определен в области пространства имен, если он используется в качестве (3.2) в программе, а определение области пространства имен не должно содержат инициализатор.

odr-used означает формирование ссылки на эту переменную или ее адрес.

std::min принимает значения параметров по ссылке, поэтому они используются как odr.

Решение:

Определите это!

class A
{
    static const int a = 5;
};

const int A::a; //definition, shall not contain initializer

Ответ 4

У меня очень странная ситуация.

template<class T> class Strange {

public:
  static const char gapchar='-';
  };

template<class T> void Strange<T> method1 {
      char tmp = gapchar;
}

template<class T> void Strange<T> method2 {
    char tmp = gapchar;
}

Я включаю класс выше, он работает уже несколько лет.

Я добавил другой метод, по существу, одну и ту же подпись и просто прочитав пробел.

Я получил ошибку undefined только для третьего метода, даже я использую все три метода.

Затем я изменил способ инициализации статической переменной

не инициализируется в определении класса:

static const char gapchar;

template<class T> const char Strange<T>::gapchar='-';

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

Ответ 5

Вы также можете сохранить значение const в локальной переменной.

class A {
public:
    static const int MY_CONST = 5;
};

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: undefined reference to 'A::MY_CONST' 
    int l = std::min<int>( j, b);  // works
}