C++模板函数调用似乎更喜欢不太专业的函数调用
C++ template function call seems to prefer the less specialized one
我正在尝试通过使用C++模板来简化我早期的一些 JSON 序列化,以减少样板代码。一切都很顺利,直到我想序列化列表等类型,因为这些本身也是模板,并且似乎需要部分模板专用化,而模板函数似乎不存在。
因此,我应用了我在这里找到的一个巧妙的小技巧: https://www.fluentcpp.com/2017/08/15/function-templates-partial-specialization-cpp/
namespace Support {
// These are in header files
template <typename T>
struct convertType{};
// Specialised template that serialises a list by iterating over its members
template <typename T>
QJsonValue toJsonValue(const QList<T> &source, convertType<QList<T>>) {
QJsonArray result;
for (auto it = source.cbegin(); it != source.cend(); it++) {
result.push_back(*it);
}
return result;
}
// "Fallback" template that generates an assertion
template <typename T>
QJsonValue toJsonValue(const T &source, convertType<T>) {
// This function should never be called.
std::string msg = "toJsonValue called with unimplemented type ";
msg += typeid (T).name();
Q_ASSERT_X(false, "toJsonValue<T>", msg.c_str()); // Always asserts.
return QJsonValue();
}
// Convenience function
template<typename T>
QJsonValue toJsonValue(const T &source) {
return toJsonValue<T>(source, convertType<T>{});
}
// This one is in the CPP file
// Integer
template <>
QJsonValue toJsonValue(const int &source, convertType<int>) {
return QJsonValue(source);
}
} // NS Support
当我用整数调用此模板时,如下所示:
qDebug() << Support::toJsonValue<int>(3713); // if not familiar with Qt, think as qDebug() being the same as std::cout.
这将输出"QJsonValue(double, 3713)",如预期的那样。
但是,当我尝试传递如下列表时:
QList<int> foo = {1, 2, 3};
qDebug() << Support::toJsonValue<QList<int>>(foo);
在我看来,代码将采用最不专业的函数模板,即生成断言的模板。我不知道为什么会发生这种情况,因为我希望它会采用专门用于QList
的功能模板。
有谁知道为什么会这样?我是否滥用了模板?
我不知道为什么会
发生这种情况,因为我希望它会采用专门用于 QList 的函数模板。
有谁知道为什么会这样?
当您致电时
Support::toJsonValue<QList<int>>(foo);
以下"便利功能"匹配
template<typename T>
QJsonValue toJsonValue(const T &source) {
return toJsonValue<T>(source, convertType<T>{});
}
T
QList<int>
.
所以内部调用
toJsonValue<T>(source, convertType<T>{})
成为
toJsonValue<QList<int>>(source, convertType<QList<int>>{});
// ........^^^^^^^^^^^^
// ........^^^^^^^^^^^^ here is the problem
明确规定T
类型为QList<int>
因此,通话无法匹配您的QList
专长
template <typename T>
QJsonValue toJsonValue(const QList<T> &source, convertType<QList<T>>)
其中模板参数T
旨在int
,模板参数为QList
。
您的呼叫只能与回退专用化匹配
template <typename T>
QJsonValue toJsonValue(const T &source, convertType<T>)
建议:让我们进行模板推导。我的意思是:不要在内部调用中显式显示模板参数
template<typename T>
QJsonValue toJsonValue(const T &source) {
return toJsonValue(source, convertType<T>{});
} // ......^^^^^^^^^^^
// ......^^^^^^^^^^^ no more "<T>" after toJsonValue
因此,双参数toJsonValue()
函数匹配(Qlist
版本,T
推导为int
,回退版本T
推导为QList<int>
),但应选择更专业的(QList
版本)。
这两者是等价的吗?似乎您创建了重载而不是部分专用化。
// Integer
template <>
QJsonValue toJsonValue(const int &source, convertType<int>) {
return QJsonValue(source);
}
// Integer
template <>
QJsonValue<int> toJsonValue(const int &source, convertType<int>) {
return QJsonValue(source);
}
相关文章:
- 函数调用中参数的顺序重要吗
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 变量没有改变?通过向量的函数调用
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 模板函数调用
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 析构函数调用
- 成员函数调用和C++对象模型
- 使用共享指针的函数调用,其对象应为 const
- C++:编译时检查匹配的函数调用对?
- 函数调用C++中的参数太少
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 返回指向对象的指针的函数调用是否为 prvalue?
- C++ 如何重载 [] 运算符并进行函数调用
- 代码的效率. 转到和函数调用
- 是同一作用域的函数部分中的函数调用
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 类型擦除的std::function与虚拟函数调用的开销