Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.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

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++ 隐式转换没有发生_C++_Templates_Implicit Conversion - Fatal编程技术网

C++ 隐式转换没有发生

C++ 隐式转换没有发生,c++,templates,implicit-conversion,C++,Templates,Implicit Conversion,我问的最后一个问题是当我试图理解另一件事时偶然发现的。。。我也不明白(不是我的日子) 这是一个相当长的问题陈述,但至少我希望这个问题可能对很多人有用,而不仅仅是我 我的代码如下: template <typename T> class V; template <typename T> class S; template <typename T> class V { public: T x; explicit V(const T & _x) :

我问的最后一个问题是当我试图理解另一件事时偶然发现的。。。我也不明白(不是我的日子)

这是一个相当长的问题陈述,但至少我希望这个问题可能对很多人有用,而不仅仅是我

我的代码如下:

template <typename T> class V;
template <typename T> class S;

template <typename T>
class V
{
public:
 T x;

 explicit V(const T & _x)
 :x(_x){}

 V(const S<T> & s)
 :x(s.x){}
};

template <typename T>
class S
{
public:
 T &x;

 explicit S(V<T> & v)
 :x(v.x)
 {}
};

template <typename T>
V<T> operator+(const V<T> & a, const V<T> & b)
{
 return V<T>(a.x + b.x);
}

int main()
{
 V<float> a(1);
 V<float> b(2);
 S<float> c( b );

 b = a + V<float>(c); // 1 -- compiles
 b = a + c;           // 2 -- fails
 b = c;               // 3 -- compiles

 return 0;
}
模板类别V;
模板类S;
模板
第五类
{
公众:
tx;
显式V(常数T和x)
:x(x){}
五级(施工安全)
:x(s.x){}
};
模板
S类
{
公众:
T&x;
显式S(V&V)
:x(v.x)
{}
};
模板
V操作员+(常数V&a、常数V&b)
{
返回V(a.x+b.x);
}
int main()
{
va(1);
vb(2);
sc(b),;
b=a+V(c);//1--编译
b=a+c;//2--失败
b=c;//3--编译
返回0;
}
表达式1和3工作正常,而表达式2无法编译

如果我理解正确,会发生以下情况:

表达式1

  • c通过使用标准转换序列(仅包含一个限定转换)隐式转换为
    const
  • 调用
    V(const S&S)
    ,并生成
    const V
    对象的时态(我们称之为t)。它已经是const限定值,因为它是一个时间值
  • 与c类似,a被转换为常量
  • operator+(const V&a,const V&b)
    被调用,导致一个类型为
    const V
    的时态,我们可以称之为q
  • 调用默认的
    V::operator=(const&V)
  • 我能到这里来吗?如果我犯了哪怕是最细微的错误,请让我知道,因为我正试图尽可能深入地了解隐式铸造

    表达式3

  • c转换为
    V
    。为此,我们有一个用户定义的转换序列:
    1.1. 第一次标准转换:
    S
    通过限定转换为
    const S

    1.2. 用户定义的转换:
    const S
    V
    通过
    V(const S&S)
    构造函数。
    1.3第二次标准转换:通过资格转换将
    V
    转换为
    const V
  • 调用默认的
    V::operator=(const&V)
  • 表达式2?

    我不明白的是为什么第二个表达式有问题。为什么以下顺序不可能

  • c转换为
    V
    。为此,我们有一个用户定义的转换序列:
    1.1. 初始标准转换:
    S
    const S
    通过资格转换。
    1.2. 用户定义的转换:
    const S
    V
    通过
    V(const S&S)
    构造函数。
    1.3. 最终标准转换:
    V
    通过鉴定转换为
    const V
  • 步骤2至6与表达式1的情况相同
  • 阅读C++标准后,我说:“嘿!也许问题出在13.3.3.1.2.3其中指出:

    如果用户定义的转换由模板转换函数指定,则第二个标准转换序列必须具有精确的匹配秩

    但事实并非如此,因为资格转换具有确切的匹配等级

    我真的不知道


    好的,不管你有没有答案,谢谢你阅读到这里:)

    只是一个猜测,但是在试图找出如何在表达式2中添加a+c时,编译器可能无法区分从V->S到S->V的转换。您假设编译器足够聪明,可以选择一个允许编译继续进行的编译器,因为其余的函数都可用,但编译器可能没有“提前读取”(可以这么说),并且在试图找到“+”运算符之前,对上转换的模糊性感到困惑


    当然,如果您添加了编译错误,也可能有助于澄清问题…

    在考虑模板匹配时,不使用隐式转换。因此,在以下简单示例中:

    template < typename T >
    void foo( T t1, T t2 ) { /* do stuff */ }
    
    int main( int argc, char ** argv ) {
        foo( 1, 1.0 );
        return 0;
    }
    
    模板
    voidfoo(tt1,tt2){/*dostuff*/}
    int main(int argc,字符**argv){
    foo(1,1.0);
    返回0;
    }
    

    即使其中一个参数可以隐式转换为另一种类型(int-double),它也不会编译。

    正如Edric指出的,在模板参数推导过程中不考虑转换。在这里,您有两个上下文,其中模板参数T可以从参数的类型推断出来:

    template<class T>
    v<T> operator+(V<T> const&, V<T> const&);
                   ~~~~~~~~~~~  ~~~~~~~~~~~~
    
    模板
    v运算符+(v常数&,v常数&);
    ~~~~~~~~~~~  ~~~~~~~~~~~~
    
    但是,您尝试使用左侧的
    V
    和右侧的S来调用此函数模板。模板参数推断的结果是左手边的T=float,而右手边则会出现错误,因为没有T,所以
    V
    等于
    S
    。这符合模板参数推断失败的条件,模板将被忽略

    如果要允许转换,运算符+不应是模板。有以下技巧:您可以将其定义为V类模板内的内联好友:

    template<class T>
    class V
    {
    public:
       V();
       V(S<T> const&); // <-- note: no explicit keyword here
    
       friend V<T> operator+(V<T> const& lhs, V<T> const& rhs) {
          ...
       }
    };
    
    模板
    第五类
    {
    公众:
    V();
    
    V(S const&);//根据标准,运算符+是一个候选函数,因为它具有正确数量的参数。因此编译器应该能够跟踪我刚才编写的转换…或者我理解的那样。至于错误消息:../main.cpp:42:错误:与“a+c”中的“operator+”不匹配(抱歉,我不知道如何在这里添加新行)正如我所说的,这需要编译器“预读”并使用V构造函数转换c,然后它才能匹配指定的自定义运算符+
    template<class T>
    struct id {typedef T type;};
    
    template<class T>
    T clip(
       typename id<T>::type min,
       T value,
       typename id<T>::type max )
    {
       if (value<min) value=min;
       if (value>max) value=max;
       return value;
    }
    
    int main() {
       double x = 3.14;
       double y = clip(1,x,3); // works, T=double
    }