& t) { return std::get(t); } template int* -6ren">
gpt4 book ai didi

c++ - 函数模板和 "normal"函数奇怪的不一致

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:26:16 24 4
gpt4 key购买 nike

我有两个几乎相同的函数(除了其中一个是模板):

int* bar(const std::variant<int*, std::tuple<float, double>>& t)
{
return std::get<0>(t);
}
template <typename... Args>
int* foo(const std::variant<int*, std::tuple<Args...>>& t)
{
return std::get<0>(t);
}

然后,他们是这样使用的:

foo(nullptr);
bar(nullptr);

第二个编译并返回 (int*)nullptr,但第一个没有(在 Visual Studio 2019 中使用 C++17 给出错误 foo: no matching overload找到)。为什么?为什么将此函数设为模板会导致它停止编译?

像下面这样使用 foo 也无济于事,因此无法推断 Args 可能不是问题所在:

foo<>(nullptr);

相反,以下内容确实有效:

foo(std::variant<int*, std::tuple<>>(nullptr));

有没有可能以某种方式避免写这么长的代码?

最佳答案

显然,如果函数参数的类型依赖于必须推导的模板参数(因为它未在 <...> 中指定),则在将参数传递给该参数时隐式转换不适用。

Source:

The function parameters that do not participate in template argument deduction (e.g. if the corresponding template arguments are explicitly specified) are subject to implicit conversions to the type of the corresponding function parameter (as in the usual overload resolution).

A template parameter pack that is explicitly specified may be extended by template argument deduction if there are additional arguments:

template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types = {int*, float*, int}
}

这也解释了为什么 foo<>(nullptr);仍然不起作用。由于编译器试图推断出额外的类型来扩展 Args ,在这种情况下,foo(nullptr); 之间似乎没有任何区别。和 foo<>(nullptr); .

关于c++ - 函数模板和 "normal"函数奇怪的不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56994776/

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