Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用户定义的转换不是';t适用于变量函数参数?为什么不呢?_C++_Templates_Implicit Conversion - Fatal编程技术网

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);