此模板函数是否正确匹配具有多个碱基的类

Will this template function correctly match a class with multiple bases?

本文关键字:函数 是否      更新时间:2023-10-16

这段代码编译并使用 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 在每个函数参数(TagPack<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)将失败。