c++ - C++ 根据参数类型自动选择正确的重载函数
问题描述
我正在创建一个OutputItem<T>
用于写入 json 对象的接口。我希望有不同的写入 json 对象的模式,因此我提供了一个重载方法json_serialize
,它接受一个SetConstructType*
orAppendConstructType*
参数,它们是ConstructType
. 在构造 时OutputItem<T>
,我希望用户在构造函数中传递 a ConstructType*
,该构造函数OutputItem<T>
将被保存以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);
解决方案
由于您无法在运行时选择重载,因此您需要一种更动态的机制。
由于您不能拥有虚拟模板,因此很难用您的外部层次结构解决这个问题。
一种替代方法是通过成员函数指针重定向。
插图(没有您的所有参数和数据):
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();
}
推荐阅读
- node.js - 无法从编辑配置文件页面更新 MongoDB
- python - 基于列值的高效逐行操作(聚合)
- c - 在不传递偏移量的情况下迭代行
- haskell - 使用 sortByFst 时出错:变量不在范围内
- javascript - 我第一次在页面上导航时不会调用头部中的特定页面脚本。代码组织质疑
- terraform - 每个环境需要有单独的通知通道
- javascript - 如何显示正在加载的内容如下:正在加载。加载..加载
- java - 使用 Android Studio 3.5 在 Kotlin 中的资源文件和 const val 之间哪种方式更好?
- vba - VBA Word - 反向遍历文档中的所有段落
- glib - GLib线程中的g_ptr_array_add()是否安全?