gpt4 book ai didi

c++ - 用户定义的转换不适用于可变参数函数参数?为什么不?

转载 作者:行者123 更新时间:2023-12-02 03:33:16 26 4
gpt4 key购买 nike

我有一个类,主要包装一个 std::variant 以及一些小的附加功能/元数据。

为了简化使用,我想提供此包装类到底层变体类型的用户定义转换,因此可以直接在其上调用诸如 std::holds_alternative 之类的函数。

我所发现的内容让我对是否以及何时应用用户定义的转换感到非常困惑。这是简化的代码。

#include <iostream>
#include <variant>

struct MyClass
{
// "MyClass" is implicitly convertible to a variant<bool,int>
operator std::variant <bool, int> ()
{
return std::variant<bool,int>(5);
}
};

void thisFunctionTakesOneSpecificVariantType (std::variant<bool,int> v)
{
std::cout << v.index();
}

template <class... types>
void thisFunctionTakesAnyVariantType (std::variant<types...> v)
{
std::cout << v.index();
}

int main ()
{
MyClass mc;

// 1. This compiles and runs as expected,
// proving the user-defined conversion (MyClass -> variant<int,bool>) exists and works "sometimes"
thisFunctionTakesOneSpecificVariantType (mc);

// 2. This compiles and runs as expected,
// proving "thisFunctionTakesAnyVariantType" is well defined
thisFunctionTakesAnyVariantType (std::variant <bool, int> (5));

// 3. But, combining 1 & 2, this fails to compile:
/* fails */ thisFunctionTakesAnyVariantType (mc); // error: no matching function for call to 'thisFunctionTakesAnyVariantType'

// 4. This is what i really want to do, and it also fails to compile
/* fails */ std::holds_alternative<int>(mc); // error: no matching function for call to 'holds_alternative'

// 5. An explicit conversion works for 3 and 4, but why not an implicit conversion?
// After all, the implicit conversion worked in #1
thisFunctionTakesAnyVariantType ( static_cast<std::variant <bool, int>> (mc) );

return EXIT_SUCCESS;
}

为什么用例 3 和 4 不能编译,而用例 1、2 和 5 可以编译?

在错误消息中,它提供了以下注释:

note: candidate template ignored: could not match 'variant<type-parameter-0-1...>' against 'MyClass'
inline constexpr bool holds_alternative(const variant<_Types...>& __v)

最佳答案

Why don't use cases 3 compile

因为 template argument deduction 中不考虑隐式转换:

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

MyClass 的转换至std::variant <bool, int>不会被考虑,然后类型推导失败。正如 #5 所示,您可以在传递到 thisFunctionTakesAnyVariantType 之前应用显式转换。 .

Why don't use cases 4 compile

与#3 相同的原因。请注意,即使您为参数包模板实参推导指定了一些模板实参,仍会尝试从函数实参中推导以下模板实参。您可以使用从推导中排除函数参数

template <class... types>
void thisFunctionTakesAnyVariantType (std::type_identity_t<std::variant<types...>> v)

然后你可以将其称为

thisFunctionTakesAnyVariantType<bool, int>(mc);

但请注意,这将使所有模板参数推导无效(并且 #2 和 5 会失败),因此这可能是一个坏主意。

顺便说一句: std::type_identity 从 C++20 开始就受支持,而且很容易实现。

关于c++ - 用户定义的转换不适用于可变参数函数参数?为什么不?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58385718/

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