【问题标题】:Generic function to serialize from std::any从 std::any 序列化的通用函数
【发布时间】:2026-02-17 21:45:02
【问题描述】:

我正在尝试创建一个函数来序列化存储为std::any 的对象。这个想法是,对象与可以序列化它的函数一起存储在 std::any 中,然后在对象上调用该函数。

我遇到了以下问题。

#include <iostream>
#include <any>

using namespace std;

template<typename T, int (*F)(T& t)>
int _GetDataFromAny(std::any& input)
{
    return F(std::any_cast<T&>(input));
}

struct MyStruct
{
    int val = 69;  
};

int Fun(MyStruct& str) { return str.val; }

template<typename T>
void DoStuff(T& s, int (*F)(T&))
{
    auto an = make_any<T>(s);
    cout << _GetDataFromAny<MyStruct, F>(an);
}

int main()
{
    MyStruct s = {71};

    DoStuff(s, Fun);     /* does not compile */
    
    /* Works fine */
    auto an = make_any<MyStruct>(s);
    cout << _GetDataFromAny<MyStruct, Fun>(an);

    return 0;
} 

此代码有 2 个版本,一个有 DoStuff 行,一个没有。 DoStuff 背后的想法是它可以构造 std::any 容器和适当的函数来序列化该对象,但是我无法编译 DoStuff(但是其他所有内容都可以编译)。

我得到的确切错误是:

main.cpp: In instantiation of ‘void DoStuff(T&, int (*)(T&)) [with T = MyStruct]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',38)">main.cpp:38:19</span>:   required from here
main.cpp:31:41: error: no matching function for call to ‘_GetDataFromAny(std::any&)’
     cout << _GetDataFromAny<MyStruct, F>(an);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
main.cpp:15:5: note: candidate: template int _GetDataFromAny(std::any&)
 int _GetDataFromAny(std::any& input)

我不完全确定模板替换失败的原因。

【问题讨论】:

  • F 是函数参数,不是编译时间常数。模板参数在编译时解析,因此它们必须是编译时常量。您必须将 F 作为模板参数传递给 DoStuff
  • 请注意:_GetDataFromAnyreserved identifier,因为它以一个下划线开头,后跟一个大写字母。您应该选择一个不同的名称。
  • @alterigel 如何指示内部函数?因为这些是模板,所以它们必须在标题中,但我想劝阻人们不要直接调用它们。
  • @Makogan “我怎样才能指出一个内部函数?” 把它们放在你自己的namespace 中。很多项目都包含一个 details 嵌套命名空间,用于提供必须公开但用户应该忽略的私有实现细节。

标签: c++ templates serialization c++17


【解决方案1】:

F 作为函数参数不能用作模板参数。这不是constant expression

F 必须是模板参数才能编译此代码。函数参数永远不是常量表达式。

【讨论】:

    最近更新 更多