繁体   English   中英

当使用 function 调用模板函数时,我遇到了一个意外的匹配模板 function 进行调用

[英]When using function calls to template functions, I am faced with an unexpected matching template function for my call

对于以下代码,为什么编译器匹配我的 function 调用与(意外)模板 function:

首先是可用的 function 模板:

// First function template
template <typename T, typename U>
auto sub(T x, U y) {
    return x - y;
}

// Second function template
template <typename T>
auto sub(T x, T y) {
    return x - y;
}

现在假设我从一个模板参数推导语句开始:

sub(5.2, 2.1);

上面的语句应该反过来使用上面提供的第二个 function 模板实例化一个 function 实例(模板函数),最终看起来像这样:

template<>
double sub<double>(double x, double y) {
    return x - y;
}

下一条语句不会实例化新模板 function,因为它将能够与之前创建的模板匹配。

sub<double>(2.3, 234.2);

现在下面的陈述是我有点困惑的地方。

sub<double>(2.3, 234.0f); // Weird one

尽管我提供了一个实际类型(double),但在模板参数中,我遇到了一个奇怪的结果。 我故意将第二个 function 参数设置为浮点数,以便与我们之前提到的 function 实例(模板函数)不完全匹配,并且预期会发生浮点提升并将浮点数提升为双精度值,然后匹配模板 function ,这不是最终发生的事情......而是它使用顶部提供的第一个 function 模板创建了一个新的 function 实例(模板函数),最终看起来像这样:

template<>
double sub<double, float>(double x, float y) {
    return x - y;
}

我感到困惑的是,我如何认为编译器更喜欢促销而不是这样的东西,或者我可能把它与其他东西混淆了,我希望有人可以澄清一下。

也困扰我的一个问题是,我不知道如何才能显式调用我真正想要的模板 function,例如:

sub<double>(2, 2);

如果我希望它调用模板 function 并且两个参数类型都是double并且只是希望我的 arguments 都从int数字转换为double怎么办。 按照这个逻辑,我不能这样做,因为编译器最终会创建一个新的 function 实例(模板函数),它看起来像这样:

template<>
double sub<double, int>(double x, int y) {
    return x - y;
}

我必须提到我不是在谈论如何转换我的 arguments 因为我很清楚我可以在它们上使用static_cast ,我也不是在谈论做这样的事情:

sub<double, double>(2, 2);

As that would of course, use the first function template to create a new function instance (template function), not use the already available template function (which was created through the use of the second function template ). 如果真的有办法,有人可以解释我怎么能做到吗? 所有这一切,主要是因为我试图真正理解概念。

您可以提供模板参数的部分列表。 例如,如果您有

template <typename A, typename B, typename C>
void foo(A, B, C);

然后这些电话

foo(1,2,3);
foo<int>(1,2,3);
foo<int, double>(1,2,3);
foo<int, double, float>(1,2,3);

都很好。

所以sub<double>(2.3, 234.2f); 仍然匹配第一个 function 模板和第二个模板的实例化,前者更好匹配,因为它不需要转换。 只有当两个匹配都同样好时,重载决议才更喜欢非模板而不是模板1 如果模板更匹配,则使用它。

当两个参数的类型不同时,可以强制选择第二个模板:

auto x = (static_cast<float(*)(float, float)>(sub))(1, 2.0);

但这当然违背了目的。 为了方便使用,你需要引入一些其他的选择机制,例如

enum class same { type };
template <typename T, same = same::type>
auto sub(T x, T y)...

... sub<double, same::type>(2.3, 234.0f) ...

1或者更确切地说,需要推导模板参数的调用与不需要推导任何内容的调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM