gpt4 book ai didi

c++ - 非静态方法指针的返回值扣除

转载 作者:行者123 更新时间:2023-12-01 14:39:35 25 4
gpt4 key购买 nike

我在玩弄指向非静态方法的函数指针,偶然发现了一些我不觉得有意义的GCC消息。让我们看一些代码:

#include<iostream>

struct X{ int print() const { std::cout << "hello"; return 0; } };
struct Y: public X{};

template<class T>
struct print_one
{
const T& t;

print_one(const T& _t): t(_t) {}

template<class Something>
void _call(Something (T::*fct)() const) const
{
std::cout << (t.*fct)() << '\n';
}

void do_print() const { _call(&T::print); }
};


int main()
{
X x;
Y y;
print_one<X>(x).do_print();
//print_one<Y>(y).do_print();
}

我已经准备好看到失败,因为可以这么说,因为我认为方法的返回值并不有助于其“ID”(编辑:其签名)。但是,这可以编译( gcc-9 --std=c++17)并且可以正常工作。

但是,如果我使用 print_one(取消注释 Y的最后一行)来实例化 main(),那么事情就往南走:
test_ptr.cpp: In instantiation of 'void print_one<T>::do_print() const [with T = Y]':
test_ptr.cpp:28:28: required from here
test_ptr.cpp:19:27: error: no matching function for call to 'print_one<Y>::_call(int (X::*)() const) const'
19 | void do_print() const { _call(&T::print); }
| ^~~~~
test_ptr.cpp:14:8: note: candidate: 'template<class Something> void print_one<T>::_call(Something (T::*)() const) const [with Something = Something; T = Y]'
14 | void _call(Something (T::*fct)() const) const
| ^~~~~
test_ptr.cpp:14:8: note: template argument deduction/substitution failed:
test_ptr.cpp:19:27: note: mismatched types 'const Y' and 'const X'
19 | void do_print() const { _call(&T::print); }
| ^~~~~

特别是 with Something = Something对我来说似乎很奇怪。此外,如果我像下面这样显式给出模板实例化,整个工作就可以了: _call<int>(&T::print)

因此,问题将是:为什么GCC不能推导模板参数 Something,尽管它不是 print方法的签名的一部分;为什么当推导遇到定义了实际方法的类派生的类时,推导会失败吗?

最佳答案

看来您有两个不利因素在起作用。首先,是从int (X::*)()int (Y::*)() is implicit的转换,因此经常可以不用考虑。经常。但是您的错误消息中提到“参数推导/替换”。

在模板自变量推导implicit conversions are not considered期间。因此,在这种情况下,您提供的int (X::*)()类型的参数与预期的int (Y::*)()不匹配。 (无论这种不匹配是否正确,我都会留给其他人使用。它存在于gcc和clang中。)如果要显式提供模板参数,则不需要参数推导,而您将跳到步骤进行隐式转换。

提供模板参数的简单方法不适合您的上下文,但确实提供了概念证明。

_call<int>(&T::print); // Specify that the return type must be `int`

通过指定 int,不需要推导出template参数。但是,这会大大破坏模板的要点,从而限制了您的选择。幸运的是,我们可以做得更好。我们可以告诉编译器如何“推断”模板参数。 (我使用了引号,因为这不是官方的模板推导步骤。)
_call<decltype(t.print())>(&T::print); // The desired generic return type

I thought the return value of a method does not contribute to its "ID" so to say.



通过“ID”,您可能指的是“ signature”?的确,(非模板)函数的签名不包括返回类型,但是您在处理类型,而不是签名。函数指针的 类型确实包括其参数的类型和其返回类型。

关于c++ - 非静态方法指针的返回值扣除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61261436/

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