c++ 用于访问nlohmann json的静态函数

osh3o9ms  于 2022-12-15  发布在  其他
关注(0)|答案(1)|浏览(151)

我想为nlohmann json库创建一个类 Package 器,所以我创建了一个类,类中有一个静态变量nlohmann::json和一个静态函数来访问它,但是当我编译它的时候,编译器说unresolved external symbol:
unresolved external symbol "private: static class nlohmann::json_abi_v3_11_2::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::json_abi_v3_11_2::adl_serializer,class std::vector<unsigned char,class std::allocator<unsigned char> > > Config::data"
下面是我的代码:

#pragma once

#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>

#include <nlohmann/json.hpp>

/**
 * @brief Class giving access to the settings of the application.
 * 
 * This class contains static methods that read configuration from file.
 * Only works on Windows OS.
 * 
 * 
 */
class Config
{
private:
    static constexpr const char* path = "Test\\PIDController";
    static constexpr const char* filename = "config.txt";

    static nlohmann::json data;
public:
    /**
     * @brief Check if config exists. If not, create it. Then load config.
     * 
     * Check if the directory of the config file exists. If not, create it.
     * Then check if the config file exists. If not, create it with default
     * configuration.
     * 
     * Use JSON format to store data using JSON for modern C++.
     * [https://github.com/nlohmann/json](https://github.com/nlohmann/json)
     * 
     */
    static void check_default_conf()
    {
        std::filesystem::path file_path = std::filesystem::path(getenv("appdata")) / std::filesystem::path(path) / std::filesystem::path(filename);
        if (!std::filesystem::is_directory(path) || !std::filesystem::exists(file_path))
        {
            bool a = std::filesystem::create_directories(std::filesystem::path(getenv("appdata")) / std::filesystem::path(path));
            std::ofstream of(file_path);
            nlohmann::json default_conf;
            default_conf["target"] = 1e-3f;
            of << std::setw(4) << default_conf;
            of.close();
        }

        // Load conf file
        std::ifstream f(file_path);
        data << f;
        f.close();
    }

    /**
     * @brief Save config file.
     * 
     */
    static void save_conf()
    {
        std::filesystem::path file_path = std::filesystem::path(getenv("appdata")) / std::filesystem::path(path) / std::filesystem::path(filename);

        std::ofstream ofs(file_path);
        ofs << std::setw(4) << data;
        ofs.close();
    }

    /**
     * @brief Get setting matching the given key.
     * 
     * @tparam T Setting type
     * @param key Setting key
     * @return Value of the entry
     */
    template <typename T>
    static T get(const char* key)
    {
        return data[key].get<T>();
    }

    /**
     * @brief Set setting matching the given key.
     * 
     * @tparam T Setting type
     * @param key Setting key
     * @param value Value to set
     * 
     * @par Returns
     *      Nothings.
     */
    template <typename T>
    static void set(const char* key, T value)
    {
        data[key] = value;
    }
};

你知道问题出在哪里吗?我想我的代码有一个错误的模式,但我不知道在哪里。
我使用的是Visual C++ 2022和C++20。

rxztt3cl

rxztt3cl1#

正如您在static members documentation中所看到的,Config类中的以下行:

class Config
{
    // ...
    static nlohmann::json data;    //  <---
    // ...
};

声明而不是定义
为了解决这个问题,你需要在一个cpp文件中添加一个definition(如果有的话,最好是Config.cpp):

nlohmann::json Config::data;

从c++17开始有一个警告:可以将data定义为Config类中的inline static成员变量(不需要额外定义):

class Config
{
    // ...
    inline static nlohmann::json data;
    // ...
};

相关问题