2017-01-09 5 views
1

ниже мой код:Неопределенная ссылка на статический переменный шаблон класса

// types.h 
template <typename T> 
struct type_to_char {}; 

template <> 
struct type_to_char<char> { 
    static constexpr char str[] = "baz"; 
}; 


// main.cpp 
#include <iostream> 
#include <string> 

#include "types.h" 

int main() { 
    std::cout << type_to_char<char>::str << std::endl; 
    return 0; 
} 

В попытке компилировать, компоновщик возвращает ошибку: undefined reference to type_to_char<char>::str

я столкнулся this answer, но я не уверен, как применить его в моем случае, поскольку шаблоны не скомпилированы. Должен ли я помещать отдельный файл .cpp в проект?

В чем разница между декларацией и определением для переменных constexpr? Такая переменная не может быть объявлена ​​без инициализатора, поэтому почему я должен поместить отдельное определение в файл .cpp?

Я был бы признателен за разъяснение по этому

ответ

2

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

// header file (type.h) 
template <typename T> 
struct type_to_char {}; 

template <> 
struct type_to_char<char> { 
    static constexpr char str[] = "baz"; 
}; 

// impementation file (type.cpp) 
constexpr char type_to_char <char>::str[]; 

// main.cpp 
#include <iostream> 
#include <type.h> 

int main() { 
    std::cout << type_to_char<char>::str << std::endl; 
    return 0; 
} 
1

Вы должны обеспечить определение в .cpp, который связан в вашей окончательной программе. Например:

// types.h 
    template <typename T> 
    struct type_to_char {}; 

    template <> 
    struct type_to_char<char> { 
     static constexpr const char str[] = "baz"; 
    }; 


    // main.cpp 
    #include <iostream> 
    #include <string> 
    #include "types.h" 

    constexpr const char type_to_char <char>::str[]; 

    int main() { 
     std::cout << type_to_char<char>::str << std::endl; 
    } 
0

Вы не можете ODR использовании статический член constexpr данные, если вы дать определение для него.
Попытка ODR использовать его, что происходит, когда вы пытаетесь сделать это:

std::cout << type_to_char<char>::str << std::endl; 

И именно поэтому требуется определение.
Вы можете легко воспроизвести проблему, как это следующим образом:

struct S { static constexpr int x = 0; }; 
int main() { auto y = &S::x; (void)y; } 

Во всяком случае, в вашем конкретном случае, это достаточно, чтобы использовать следующее заявление:

static constexpr char *str = "baz"; 

Если вы можете использовать его вместо массива type, вам не нужно явно указывать type_to_char<char>::str.