gpt4 book ai didi

c++ - 如果参数类型取决于模板参数,为什么编译器不能推断返回类型

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

尝试在基于另一个模板参数的模板中选择重载集 (foo) 的函数时出现模板推导错误:

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int";
}

void foo(double a) {
std::cout << "double";
}

template <typename T, typename R>
void print(const T& data, R(*fun)(typename T::type) ) {
fun(data.value);
}

struct IntData{
using type = int;
type value;
};

int main()
{
IntData x{1};
print(x, foo);
}

我收到以下错误:

In function 'int main()':
27:15: error: no matching function for call to 'print(IntData&, <unresolved overloaded function type>)'
27:15: note: candidate is:
15:6: note: template<class T, class R> void print(const T&, R (*)(typename T::type))
15:6: note: template argument deduction/substitution failed:
27:15: note: couldn't deduce template parameter 'R'

由于模板推导应该从左到右进行,我的假设是一旦推导了 T 的类型,也应该可以推导 R 的类型。实际上,我可以在调用 print 时摆脱错误

print<IntData>(x, foo);

这似乎表明一旦 T 已知,R 实际上就可以推导出来。那么,如果应该推导两个参数,为什么它不起作用呢?

谢谢!

最佳答案

我相信这是因为您将 R 作为函数指针参数的返回类型。

注意这句话from a previous question

So, when we ask about the signature of a function, we have to give two answers:

For functions that are specializations of function templates, the signature includes the return type.

For functions that are not specializations, the return type is not part of the signature.

由于 foo 只是一个重载函数,而 void 不是 foo 函数签名的一部分,R不会帮助编译器推断正确的函数重载。因此,将 foo 用作函数指针在 main 的范围内是不明确的。编译器通常通过匹配提供的参数的类型来解决重载,当函数指针本身没有时,编译器就没有重载。

我相信这是最可靠的解决方案,包括一个中间函数来解决以前不明确的函数指针。除了 int 之外,我还包括了一些其他类型,以展示将 auto 与下面提到的策略一起使用的灵 active 。

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int" << std::endl;
}

void foo(double a) {
std::cout << "double" << std::endl;
}

bool foo(char a) {
std::cout << "char" << std::endl;
return true;
}

template <typename T, typename R>
R print(const T& data, R(*fun)(typename T::type) ) {
return fun(data.value);
}

struct IntData{
using type = int;
type value;
};
struct DoubleData{
using type = double;
type value;
};
struct CharData{
using type = char;
type value;
};
template <typename T>
auto print2(const T& data)
{
auto(*fooResolved)(typename T::type) = foo;
return print(data,fooResolved);
}

int main()
{
IntData x{1};
print2(x);

DoubleData y{1.0};
print2(y);

CharData z{'a'};
bool result = false;
std::cout << "bool before: " << result << std::endl;
result = print2(z);
std::cout << "bool after : " << result << std::endl;
}

这里还有一些可能的解决方案来帮助说明问题:

(注意更改是删除 R 作为第二个模板参数)

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int";
}

void foo(double a) {
std::cout << "double";
}

template <typename T>
void print(const T& data, void(*fun)(typename T::type) ) {
fun(data.value);
}

struct IntData{
using type = int;
type value;
};

int main()
{
IntData x{1};
print(x, foo);
}

还有这个(直接传值,允许多种返回类型)

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int";
}

void foo(double a) {
std::cout << "double";
}

template <typename T, typename R>
void print(const T& data, R (*fun)(T) ) {
fun(data);
}

struct IntData{
using type = int;
type value;
};

int main()
{
IntData x{1};
print(x.value, foo);
}

并进一步说明原问题(参见现在推导的返回类型)

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int" << std::endl;
}

bool foo(double a) {
std::cout << "double" << std::endl;
return true;
}

template <typename T, typename R>
R print(const T& data, R (*fun)(T) ) {
return fun(data);
}

struct IntData{
using type = int;
type value;
};
struct DoubleData{
using type = double;
type value;
};

int main()
{

IntData x{1};
print(x.value, foo);

//foo(int) does not return a value
//bool test = print(x.value, foo); // Does not compile

DoubleData y{1.0};

bool result = false;
result = print(y.value, foo);
std::cout << result << std::endl;

}

当我们这样做的时候,您也可以通过明确指定您想要的 foo 来解决给定原始代码的问题

#include <iostream>
#include <string>

void foo(int a){
std::cout << "int";
}

void foo(double a) {
std::cout << "double";
}

template <typename T, typename R>
void print(const T& data, R(*fun)(typename T::type) ) {
fun(data.value);
}

struct IntData{
using type = int;
type value;
};

int main()
{
IntData x{1};
void(*fooResolved)(int) = foo;
print(x, fooResolved);
}

关于c++ - 如果参数类型取决于模板参数,为什么编译器不能推断返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62204954/

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