You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带额外不可推导模板参数的函数重载是否符合C++标准?

C++ Template Overload & Deduction: Compliance & Behavior Explained

Great question! First off: your code is 100% compliant with the C++ standard—this isn't a compiler-specific extension. Now let's verify your assumptions and walk through the standard rules that govern this behavior:

1. What happens when calling fn(x1)?

Your first assumption is spot-on: the second fn overload is quietly discarded, and this is an example of SFINAE (Substitution Failure Is Not An Error).

Here's why:
When resolving overloads, the compiler tries to deduce template parameters for each candidate. For the second overload:

template <class Xs, class A> constexpr auto fn(X<A> const& x) { return Xs(x.a - 1); }

You only pass the argument x1 (type X<int>), with no explicit template argument for Xs. Since Xs only appears in the return type (which isn't a valid context for template parameter deduction), the compiler can't figure out what Xs should be.

Per the C++ standard, this deduction failure doesn't trigger a compile error—SFINAE dictates we just drop this overload from the candidate list. That leaves only the first overload:

template <class A> constexpr auto fn(X<A> const& x) { return X<A>(x.a - 1); }

Here, A is easily deduced as int from x1's type X<int>, so it instantiates to fn(X<int> const&) and returns X<int>{2}.

2. What happens when calling fn<X<double>>(x1)?

Your core idea here is correct, but let's clarify a small detail about why the first overload is discarded:

When you explicitly specify X<double> as a template argument, we check each overload:

  • For the first fn overload (which has one template parameter A), X<double> gets bound to A. This instantiates the function to fn(X<X<double>> const&)—but your argument x1 is X<int>, which doesn't match X<X<double>> at all. This overload is rejected because the function signature doesn't match the argument type, not because of SFINAE.
  • For the second fn overload (which has two template parameters Xs and A), X<double> is bound to Xs, and A is deduced as int from x1's type X<int>. This gives us fn<X<double>, int>(X<int> const&), which perfectly matches your call and returns X<double>{2.0}—so this is the overload that gets selected.

To recap: the first overload is eliminated here due to a type mismatch after instantiation, not a deduction failure like in the first case.


内容的提问来源于stack exchange,提问作者Holt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:37:33