【发布时间】:2019-07-11 17:45:59
【问题描述】:
我有两个几乎相同的函数(除了其中一个是模板):
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 found)。为什么?为什么将此函数设为模板会导致它停止编译?
像下面这样使用foo 也无济于事,因此无法推断出Args 可能不是问题:
foo<>(nullptr);
相反,以下方法确实有效:
foo(std::variant<int*, std::tuple<>>(nullptr));
是否有可能以某种方式避免需要写这么长的方式?
【问题讨论】:
-
模板不进行转换。
nullptr不是variant<...> -
@Barry 你的意思是标准规定在函数模板中禁止隐式转换吗?
-
模板尝试匹配您提供的类型。他们不会尝试扩展为与接受您的论点兼容的其他内容。在这种情况下,即使它确实允许此类转换,使用 nullptr 调用模板仍然会失败,因为无法推断出 Args... 应该包含什么类型。
-
@ChrisUzdavinis
foo<>(nullptr);也不起作用,尽管Args是已知的。 -
@YanB。显然,在这种情况下它是未知的。
foo<>表示at least在Args中有0个类型,没有任何意义。
标签: c++ visual-c++ c++17