【问题标题】:C++ automatically choose correct overloaded function based on argument typeC++ 根据参数类型自动选择正确的重载函数
【发布时间】:2021-11-14 03:29:38
【问题描述】:

我正在创建一个接口 OutputItem<T> 用于写入 json 对象。我希望有不同的写入 json 对象的模式,因此我提供了一个重载方法json_serialize,它采用SetConstructType*AppendConstructType* 参数,它们是ConstructType 的派生结构。在构造OutputItem<T> 时,我希望用户在OutputItem<T> 的构造函数中传递一个ConstructType*,它将被保存到const ConstructType* constructType,以便稍后在公共方法void write(nlohmann::json& json) 时自动选择正确的重载类型被调用。

但是我遇到了一个错误:

'void OutputItem::json_serialize(const SetConstructType *,nlohmann::json &)':无法将参数 1 从 'const ConstructType *' 转换为 'const SetConstructType *'

有人可以告诉我实现这种自动重载解决方案的正确方法吗?此外,这是 SFINAE 设计的一个示例吗?

谢谢

struct ConstructType {

protected:
    ConstructType() {}
};
struct SetConstructType : public ConstructType {};
struct AppendConstructType : public ConstructType {};

static SetConstructType*  SetConstruct;
static AppendConstructType*  AppendConstruct;

template<typename T>
struct OutputItem {

    OutputItem(const std::string& cgroupName, const std::string& citemName, const T& cdata, ConstructType* cconstructType) 
: itemName(citemName), groupName(cgroupName), data(cdata), constructType(cconstructType) {}
    
    const std::string itemName;
    const std::string groupName;
    const T data;

    const ConstructType* constructType;

    void write(nlohmann::json& json) {
        json_serialize(constructType, json);
    }

private:

    void json_serialize(const SetConstructType*, nlohmann::json& json) {
        json[groupName][itemName] = data;
    }

    void json_serialize(const AppendConstructType*, nlohmann::json& json) {
        json[groupName][itemName].push_back(data);
    }
};

用法

    json response;

    OutputItem<int> item1("testgroup", "item1", 2, AppendConstruct);
    OutputItem<int> item2("testgroup", "item2", 2, SetConstruct);
    item1.write(response);
    item2.write(response);

【问题讨论】:

  • 重载解析发生在编译时,基于编译时类型。您不能根据运行时类型选择重载。
  • 请发布错误信息。另外,也许在问题中明确说明您正在使用 nlohman json 库
  • 糟糕 - 我注释掉了导致错误的行。 xD
  • 抱歉,C++ 不能这样工作。在运行时,重载决议的等价物是虚拟方法分派。你熟悉虚拟类方法吗?
  • @AdrianMole 这很奇怪,我也在使用 MSVC C++17。我现在也添加了错误消息。

标签: c++ overloading sfinae overload-resolution


【解决方案1】:

由于您无法在运行时选择重载,因此您需要一种更动态的机制。
由于无法使用虚拟模板,因此很难使用外部层次结构解决此问题。

另一种选择是通过成员函数指针重定向。

插图(没有您的所有参数和数据):

enum class Construction
{
    Set,
    Append
};

template<typename T>
class OutputItem {
public:
    OutputItem(Construction kind): construct(select(kind)) {}
    void write() { (this->*construct)(); }

private:
    using ConstructType = void (OutputItem::*)();
    ConstructType construct;
    
    ConstructType select(Construction c)
    {
        static ConstructType cs[] = { &OutputItem::setConstruct, 
                                      &OutputItem::appendConstruct };
        return cs[static_cast<int>(c)];
    }
    void setConstruct() { std::cout << "Set\n"; }
    void appendConstruct() { std::cout << "Append\n"; }
};

//...
int main()
{
    OutputItem<int> o0(Construction::Set);
    o0.write();
    OutputItem<std::string> o1(Construction::Append);
    o1.write();
}

【讨论】:

    猜你喜欢
    • 2022-12-09
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多