Все работает в Visual Studio 2017, но я получаю ошибки компоновщика в GCC (6.5.0).
Вот пример кода, который изолирует мою проблему:
#include <iostream>
struct Foo{
static constexpr const char* s[] = {"one","two","three"};
};
int main(){
std::cout << Foo::s[0] << std::endl; //this works in both compilers
const char* const* str_ptr = nullptr;
str_ptr = Foo::s; //LINKER ERROR in GCC; works in VS
std::cout << str_ptr[1] << std::endl; //works in VS
return 0;
}
В GCCЯ получаю undefined reference to 'Foo::s'
.Мне нужно, чтобы инициализация Foo::s
оставалась в объявлении структуры, поэтому я использовал constexpr
.Есть ли способ ссылаться на Foo::s
динамически, то есть с указателем?
Дополнительная справочная информация
Теперь я объясню , почему Я хочу это сделать.Я занимаюсь разработкой встроенного программного обеспечения для управления конфигурацией устройства.Программное обеспечение загружает файлы конфигурации, которые содержат имя параметра и его значение.Настраиваемый набор параметров определяется во время компиляции, но должен быть модульным, чтобы можно было легко добавлять новые параметры и расширять их по мере продолжения разработки устройства.Другими словами, их определение должно находиться в одном месте в кодовой базе.
Моя фактическая кодовая база - это тысячи строк, и она работает в Visual Studio, но вот пример с развернутой игрушкой:
#include <iostream>
#include <string>
#include <vector>
//A struct for an arbitrary parameter
struct Parameter {
std::string paramName;
int max_value;
int value;
const char* const* str_ptr = nullptr;
};
//Structure of parameters - MUST BE DEFINED IN ONE PLACE
struct Param_FavoriteIceCream {
static constexpr const char* n = "FavoriteIceCream";
enum { vanilla, chocolate, strawberry, NUM_MAX };
static constexpr const char* s[] = { "vanilla","chocolate","strawberry" };
};
struct Param_FavoriteFruit {
static constexpr const char* n = "FavoriteFruit";
enum { apple, banana, grape, mango, peach, NUM_MAX };
static constexpr const char* s[] = { "apple","banana","grape","mango","peach" };
};
int main() {
//Set of parameters - determined at compile-time
std::vector<Parameter> params;
params.resize(2);
//Configure these parameters objects - determined at compile-time
params[0].paramName = Param_FavoriteIceCream::n;
params[0].max_value = Param_FavoriteIceCream::NUM_MAX;
params[0].str_ptr = Param_FavoriteIceCream::s; //!!!! LINKER ERROR IN GCC !!!!!!
params[1].paramName = Param_FavoriteFruit::n;
params[1].max_value = Param_FavoriteFruit::NUM_MAX;
params[1].str_ptr = Param_FavoriteFruit::s; //!!!! LINKER ERROR IN GCC !!!!!!
//Set values by parsing files - determined at run-time
std::string param_string = "FavoriteFruit"; //this would be loaded from a file
std::string param_value = "grape"; //this would be loaded from a file
for (size_t i = 0; i < params.size(); i++) {
for (size_t j = 0; j < params[i].max_value; j++) {
if (params[i].paramName == param_string
&& params[i].str_ptr[j] == param_value) {
params[i].value = j;
break;
}
}
}
return 0;
}
Как видите, задействованы перечисления и массивы строк, и они должны совпадать, поэтому в целях обслуживания мне нужно хранить их в одном месте.Кроме того, поскольку этот код уже написан и будет использоваться как в среде Windows, так и в Linux, чем меньше исправление, тем лучше.Я бы предпочел не переписывать тысячи строк только для того, чтобы компилировать их в Linux.Спасибо!