gpt4 book ai didi

c++ - 从封闭的模板类推导返回类型时函数解析失败

转载 作者:太空狗 更新时间:2023-10-29 21:04:12 25 4
gpt4 key购买 nike

我一直在尝试为定点类型实现一个复数类,其中乘法运算的结果类型将是输入类型的函数。我需要一些函数,我可以用复数乘复数,也可以用实数乘复数。

这本质上是代码的简化版本。其中 A 是我的复杂类型。

template<typename T1, typename T2> struct rt {};

template<> struct rt<double, double> {
typedef double type;
};
//forward declaration
template<typename T> struct A;

template<typename T1, typename T2>
struct a_rt {
typedef A<typename rt<T1,T2>::type> type;
};

template <typename T>
struct A {
template<typename T2>
typename a_rt<T,T2>::type operator*(const T2& val) const {
typename a_rt<T,T2>::type ret;
cout << "T2& called" << endl;
return ret;
}
template<typename T2>
typename a_rt<T,T2>::type operator*(const A<T2>& val) const {
typename a_rt<T,T2>::type ret;
cout << "A<T2>& called" << endl;
return ret;
}
};

TEST(TmplClassFnOverload, Test) {
A<double> a;
A<double> b;
double c;
a * b;
a * c;
}

代码无法编译,因为编译器正在尝试实例化 a_rt模板与 doubleA<double> .我不知道引擎盖下发生了什么,因为我想编译器应该选择更专业的 operator*(A<double>&)所以a_rt只会用 <double, double> 实例化作为参数。

能否请您向我解释一下为什么这行不通?如果这是一个限制,我应该如何解决这个问题。

非常感谢!

unittest.cpp: In instantiation of 'a_rt<double, A<double> >':
unittest.cpp:198: instantiated from here
unittest.cpp:174: error: no type named 'type' in 'struct rt<double, A<double> >'

更新

编译器似乎对以下更改感到满意。我在这里缺少一些微妙之处。感谢有人可以指导我了解编译器在这两种情况下所做的事情。

    template<typename T2>
A<typename rt<T,T2>::type> operator*(const T2& val) const {
A<typename rt<T,T2>::type> ret;
cout << "T2& called" << endl;
return ret;
}
template<typename T2>
A<typename rt<T,T2>::type> operator*(const A<T2>& val) const {
A<typename rt<T,T2>::type> ret;
cout << "A<T2>& called" << endl;
return ret;
}

最佳答案

在 C++ 中解析函数调用分五个阶段进行:

  1. name lookup:这会找到两个版本的 operator*
  2. 模板参数推导:这将应用于步骤 1) 中找到的所有函数
  3. 过载决议:将选择最佳匹配
  4. 访问控制:实际上是否可以调用最佳匹配(即是否不是私有(private)成员)
  5. virtuality:如果涉及虚函数,可能需要在 vtable 中查找

首先请注意,永远不会推导返回类型。您只是不能重载返回类型operator* 的模板参数被推导然后替换到返回类型模板中。

那么在调用 a * b; 时会发生什么? ?首先,operator*两个 版本推导出他们的论点。对于第一次过载,T2被推断为 A<double> ,对于第二次重载 T2解析为 double .如果有多个重载,标准说:

14.7.1 Implicit instantiation [temp.inst] clause 9

If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated (14.8.3).

因此,在生成候选函数集时,在参数推导结束时(因此在重载决策之前)模板被实例化,你会得到一个错误,因为 rt没有嵌套 type .这就是为什么不会选择更专业的第二个模板的原因:不会发生重载解析。您可能已经预料到此替换失败不会是一个错误。然而,标准说:

14.8.2 Template argument deduction [temp.deduct] clause 8

If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed. — end note ]

在您的原始代码中,typename a_rt<T,T2>::type返回类型不是直接上下文。只有在模板实例化期间才会对其进行评估,然后缺少嵌套的 typert是一个错误。

在您更新的代码中 A<typename rt<T,T2>::type>返回类型是直接上下文,替换失败不是错误 (SFINAE) 适用:非推导函数模板只是从重载解析集中删除,剩下的一个被调用。

使用更新后的代码,输出将是:

> A<T2>& called     
> T2& called

关于c++ - 从封闭的模板类推导返回类型时函数解析失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11856637/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com