相同的外部结构只有一个功能不同

Same outer structure only one difference between functions

除了 what 变量修改之外,我有很多功能大致相同

struct example
{
    std::string name;
    std::string category;
};

using ObjName = std::string;
using Value = std::string;

bool updateName(const ObjName &name, const Value& value) ...
bool updateCategory(const ObjName &name,const Value& value)
{
    //  boost optional pointing to struct reference
    auto obj = findOjb(name);
    if (obj)
    {
        obj.get().category = value; // variable name changes 
        return true;
    }
    return false;
}

我想知道如何合并代码? 我怀疑它可能会涉及模板 traites/functors 但我不确定如何处理它有什么想法吗?

有点hacky,但这可能是一个使用offsetof:

的解决方案(未经测试的代码)
struct example
{
    std::string name;
    std::string category;
};

bool updateVariable(const size_t offset, std::string value)
{
    // your code ...

    // ASSIGNMENT: get address, apply offset and assign value
    *(&rule.get() + offset) = cat;

    // rest of your code
}

bool updateName(const ObjName &oldname, const ObjName& newName)
{
    return updateVariable(offsetof(struct example, name), newName));
}

bool updateCategory(const ObjName &name, Category &cat)
{
    return updateVariable(offsetof(struct example, category), cat));
}

我假设 ObjNameCategorystringtypedef 或者可以隐式转换。

您仍然需要为每个成员变量添加一个单行函数,如果您想坚持硬编码结构,这在 C++ 中很难避免。您可能需要考虑将整个结构定义转换为数据,例如从文件加载,打开其他可能性。

重新编写 Daerst 的代码以删除可怕的 offsetof 以支持指向成员的指针...

struct example
{
    std::string name;
    std::string category;
};

bool updateVariable(const ObjName &name, std::string example::*member, std::string const &value)
{
    // your code ...

    // Access
    rule.get().*member = value

    // rest of your code
}

bool updateName(const ObjName &oldname, const ObjName& newName)
{
    return updateVariable(name, &example::name, newName));
}

bool updateCategory(const ObjName &name, Category &cat)
{
    return updateVariable(name, &example::category, cat));
}

你可以使用 lambdas:

template <typename Accessor>
bool updateVariable(const ObjName& name, const Value& value, Accessor access) {
    auto obj = findObj(name);
    if (obj)
    {
        access(obj.get()) = value;
        return true;
    }
    return false;
}
bool updateCategory(const ObjName& name, const Value& value) {
    return updateVariable(name, value,
        [](Example& e) -> Value& { return e.category; });
}

这比指向成员的解决方案更灵活一些。您可以通过让 lambda 执行设置而不是返回引用来使其更加灵活。

你可以使用如下特征:

#include <string>
#include <assert.h>

struct example
{
   std::string name;
   int category;
};

struct nameDesc
{
   typedef std::string valuetype;
   static void set(example& obj, const valuetype& val)
   {
      obj.name = val;
   }
};
struct categoryDesc
{
   typedef int valuetype;
   static void set(example& obj, const valuetype& val)
   {
      obj.category = val;
   }
};


example test; // just for testing...
example& findObj(const std::string &name)
{
   // just for testing...
   return test;
}
template <typename V>
bool update(const std::string &objName, const typename V::valuetype& value)
{
   example& obj = findObj(objName);
   V::set(obj, value);
   return true;
}
bool updateName(const std::string &objName, const std::string& value) { return update<nameDesc>(objName, value); }
bool updateCategory(const std::string &objName, int value) { return update<categoryDesc>(objName, value); }

int main()
{
   update<nameDesc>("objname", "asdf");
   update<categoryDesc>("objname", 1234);
   assert(test.name == "asdf");
   assert(test.category == 1234);

   updateName("objname", "qwer");
   updateCategory("objname", 7890);
   assert(test.name == "qwer");
   assert(test.category == 7890);
   return 0;
}

如果可能的话,我建议您看看 boost::spirit / BOOST_FUSION_ADAPT_STRUCT。