此模板函数是否正确匹配具有多个碱基的类
Will this template function correctly match a class with multiple bases?
这段代码编译并使用 clang 运行良好,但 gcc 给出了编译错误:
没有匹配函数来调用"解包(标签1,A3&)"
那么它有效的 c++ 吗?
#include <type_traits>
#include <utility>
#include <cassert>
template <class Tag, class Value>
class Pack
{
public:
Pack(const Value& value) : _value(value) {}
Value value() const { return _value; }
private:
Value _value;
};
template<class Tag, class Value>
decltype(auto) unpack(Tag, Pack<Tag, Value>& pack) {
return pack.value();
}
struct tag1 {};
struct tag2 {};
struct A3 : Pack<tag1, int>, Pack<tag2, double> {
A3(int x, double y) : Pack<tag1, int>(x), Pack<tag2, double>(y) {}
};
int main() {
A3 a3(1, 2);
assert(unpack(tag1(), a3) == 1);
assert(unpack(tag2(), a3) == 2);
}
Tag
在每个函数参数(Tag
和 Pack<Tag, Value> &
)的推导上下文中。模板参数推导是针对每个单独执行的,结果必须匹配。当试图从A3
推导出Pack<Tag, Value>
时,可以推导两种可能的推导,因此类型推导失败。
最简单的解决方法可能是摆脱标签函数参数,而只是使用显式模板参数调用unpack
- unpack<tag1>(a3)
并不比unpack(tag1(), a3)
更详细。如果您仍然喜欢原始语法,可以编写转发器:
template<class Tag, class SomePack>
decltype(auto) unpack(Tag, SomePack& pack) { return unpack<Tag>(SomePack); }
这不仅是多重继承的问题。这也是模板实例化的问题。
表达式 unpack(tag1(), a3)
与具有签名unpack(tag1, Pack<tag1, A3> &)
的函数调用匹配,当 pack 的类型为 Pack<tag1, A3>
时,return pack.value()
不明确。
这意味着decltype(auto)
的编译器(假设C++14)将失败。
相关文章:
- 函数是否可以访问传递给main()的参数
- 根据某个函数是否存在启用模板
- 无论如何,我可以确定构造函数是否存在吗?
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何检查函数是否在LLVM Instrumentation pass的ModulePass的系统头文件中定义?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 在对象构造期间,将指向尚未构造的子对象的指针传递给另一个子对象的构造函数是否危险?
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 由并发无序映射查找线程调用的函数是否安全?
- 使用静态成员函数而不是普通函数是否有任何开销?
- 从其存储的回调中删除 std::函数是否安全
- 析构函数是否会自动调用 delete[] C++?
- 构造函数是否有一种现代C++方法来了解其'container'类?
- 循环中本地对象的析构函数是否保证在下一次迭代之前被调用?
- 移动构造函数是否C++过时?
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 此函数是否会在C++中创建内存泄漏?
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 如何检测构造函数是否与抛出的析构函数无关