nlohmann::json 的模板问题

Template issue with nlohmann::json

提问人:Joseph Larson 提问时间:1/25/2022 最后编辑:Marek RJoseph Larson 更新时间:4/25/2022 访问量:942

问:

这是我的代码和错误,下面我将展示一些有效的代码。

#include <iostream>
#include <string>

#include <nlohmann/json.hpp>

using JSON = nlohmann::json;
using std::cout;
using std::endl;
using std::string;

template <class ObjectType>
void dump(const JSON &json) {
    for (auto &[key, value]: json.items()) {
        string foo = value.get<std::string>();
        cout << "Key: " << key;
        cout << " Value: " << foo << endl;
    }
}

int main(int, char **) {
    JSON json;
    json["alpha"] = "beta";
    dump<string>(json);
} 
-$ g++ -std=c++17 Foo.cpp -o Foo && Foo
Foo.cpp: In function ‘void dump(const JSON&)’:
Foo.cpp:14:37: error: expected primary-expression before ‘>’ token
   14 |   string foo = value.get<std::string>();
      |                                     ^
Foo.cpp:14:39: error: expected primary-expression before ‘)’ token
   14 |   string foo = value.get<std::string>();
      |                                       ^

现场演示

如果我注释掉该行并将 main 中的调用更改为 ,一切正常。templatedump(json)

我真正的问题实际上是在模板类中,而不是模板函数中,但这是我可以创建的最简化的版本。我真正想要的是这句话:

    ObjectType obj = value.get<ObjectType>();

但这将是下一步。

有谁知道我做错了什么以及如何解决它?

C++ NLohmann-JSON

评论

3赞 HolyBlackCat 1/25/2022
无法重现
0赞 Joseph Larson 1/25/2022
@HolyBlackCat我不知道该告诉你什么。我从样本中剪切和粘贴。我想知道它是否是 G++ 的一个版本。 和 nlohmann JSON 版本 3.10.4。操作系统是 Ubuntu 20.04。g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
4赞 StoryTeller - Unslander Monica 1/25/2022
@HolyBlackCat - godbolt 上的 GCC 重现了它(您尝试了 Clang)。我认为这是一个 GCC 错误。
3赞 StoryTeller - Unslander Monica 1/25/2022
至于如何解决它...... 作品。但从各方面来看,它不应该是必需的。 不依赖。value.template get<ObjectType>()value
1赞 Kevin 1/25/2022
如果我用 替换 ,它就会编译。我不知道为什么。for (auto &[key, value] : json.items()) { ... }for (auto &pair : json.items()) { auto &[key, value] = pair; ... }

答:

2赞 C2P1 4/25/2022 #1

虽然它与 MSVC 和 Clang 按原样工作,但为了让它在 GCC 上编译而不改变变量的结构或分配,GCC 需要指定依赖类型的模板消歧器,以便正确解析它。

片段:

using JSON = nlohmann::json;

template <class ObjectType>
void dump(const JSON &json) {
    for (auto &[key, value]: json.items()) {
        std::string foo = value.template get<std::string>(); // Here
        std::cout << "Key: " << key;
        std::cout << " Value: " << foo << endl;
    }
}

这是由于被解析为,即 后跟小于运算符。value.get<std::string>()value.get < ...value.get

我想知道在函数模板化时发生这种情况的原因是否是由于模板推导规则和为类型提供的现有模板,这最终意味着编译器已经相信它已经在解析后续模板专用化之前推断出模板类型。nlohmann::JSONvalue.getvalue.get<std::string>