C++ 用户定义的转换不是';t适用于变量函数参数?为什么不呢?
我有一个类,它主要包装了一个C++ 用户定义的转换不是';t适用于变量函数参数?为什么不呢?,c++,templates,implicit-conversion,C++,Templates,Implicit Conversion,我有一个类,它主要包装了一个std::variant,还有一些次要的附加功能/元数据 为了使用简单,我想提供一个用户定义的将这个包装类转换为底层变量类型的转换,这样就可以直接在它上面调用像std::holds\u alternative这样的函数 我所发现的让我对是否以及何时应用用户定义的转换感到非常困惑。下面是简化的代码 #include <iostream> #include <variant> struct MyClass { // "MyClass" i
std::variant
,还有一些次要的附加功能/元数据
为了使用简单,我想提供一个用户定义的将这个包装类转换为底层变量类型的转换,这样就可以直接在它上面调用像std::holds\u 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;
}
#包括
#包括
结构MyClass
{
//“MyClass”可隐式转换为变量
运算符std::variant()
{
返回std::variant(5);
}
};
void此函数采用特定的variantType(std::variantV)
{
std::cout规则就是这样制定的。其他比我更有知识的人可能会来给你这里的确切规则(考虑模板替换和转换),但最终它是什么,你不能改变它
为了考虑转换,您的类需要继承自std::variant
。您的所有示例都将编译。但是,我不愿意推荐这种方法,因为在这里,合成似乎是正确的设计
我要做的是提供一个转换方法。你会失去它隐含的一面,但也许这不是一个坏主意,至少考虑到替代方案
struct MyClass
{
std::variant<bool, int> to_var() const
{
return {5};
}
}
struct MyClass
{
std::变量到_var()常量
{
返回{5};
}
}
此函数采用一个变量类型(mc.to_var());
std::holds_alternative(mc.to_var());
可以将转换运算符放在它工作的情况下,但是考虑它是否只是增加混淆。
为什么不编译用例3
因为隐式转换不考虑在:
类型演绎不考虑隐式转换(除了上面列出的类型调整):这是以后发生的工作。
从MyClass
到std::variant
的转换将不被考虑,然后类型推断失败。正如#5所示,在传递到之前,您可以应用显式转换,该函数采用变量类型
为什么不编译用例4
与#3的原因相同。请注意,即使您为参数包模板参数推断指定了一些模板参数,仍然会尝试从函数参数推断出以下模板参数。您可以使用以下命令从推断中排除函数参数:
template <class... types>
void thisFunctionTakesAnyVariantType (std::type_identity_t<std::variant<types...>> v)
模板
void此函数采用变量类型(std::type\u identity\u t v)
那么你可以称之为
thisFunctionTakesAnyVariantType<bool, int>(mc);
此函数采用一种变量类型(mc);
但请注意,这将使所有模板参数推断无效(并且#2和#5将失败),因此这可能是个坏主意
顺便说一句:从C++20开始就支持它,即使它很容易实现。很好,谢谢你提供了这些有价值的建议!我没有考虑过从variant继承作为一种可能的解决方案,尽管我同意你的看法,它在我的设计中并不理想。我可能会使用访问器方法(“to_var()”)这很好,只是比我希望的更详细。谢谢你!特别是指定了“即使你为参数包指定了一些模板参数”的细节,它仍然不起作用-我也试过了,应该包括在我的原始问题中。
thisFunctionTakesAnyVariantType<bool, int>(mc);