C++ C++;重载函数调用中的隐式转换和歧义
我面临着以下问题:我有一个类V(比如向量),我可以从中生成两个类:CI和I(想想常量迭代器和迭代器)。 如果我有一个常数V,那么我只能生成CI(再想想迭代器和常数迭代器) 基本上,我想用(CI)代替(const V&V),用(I)代替(V&V)。此外,我希望仍然能够将V obj直接传递给期望I或CI的函数,从而实现从V和const V到CI和I的隐式转换 我面临的问题是,虽然重载函数可以区分(const V&V)和(V&V),但当我通过V obj时,它们无法“区分”(CI)和(I) 代码:C++ C++;重载函数调用中的隐式转换和歧义,c++,overloading,implicit-conversion,C++,Overloading,Implicit Conversion,我面临着以下问题:我有一个类V(比如向量),我可以从中生成两个类:CI和I(想想常量迭代器和迭代器)。 如果我有一个常数V,那么我只能生成CI(再想想迭代器和常数迭代器) 基本上,我想用(CI)代替(const V&V),用(I)代替(V&V)。此外,我希望仍然能够将V obj直接传递给期望I或CI的函数,从而实现从V和const V到CI和I的隐式转换 我面临的问题是,虽然重载函数可以区分(const V&V)和(V&V),但当我通过V obj时,它们无法“区分”(CI)和(I) 代码: st
struct V {};
struct I
{
I( V& v ){}
};
struct CI
{
CI( const V& v ){} //I would like to say const only
};
void fun( I i )
{
double x = 1.0;
}
void fun( CI ci )
{
double x = 2.0;
}
void fun2( V& v )
{
double x = 1.0;
}
void fun2( const V& v )
{
double x = 2.0;
}
注意,我可以在V中定义conversions操作符(是否等效?),而不是在CI和I中定义构造函数。现在:
V v;
const V cv;
fun2( v );
fun2( cv );
fun( v ); //AMBIGUOUS!
fun( cv );
有没有一种方法可以在不添加任何额外间接寻址的情况下解决此问题(即不能修改fun函数,必须将v直接传递给fun,但您可以自由修改其他所有内容)
提前感谢您的帮助 使用
typedef
s怎么样
typedef V& I;
typedef const V& CI;
编辑:
否。请参阅注释:)此处需要的是显式构造函数:
struct I
{
explicit I( V& v ){}
};
struct CI
{
explicit CI( const V& v ){} //I would like to say const only
};
<>太多的C++程序员忽略构造函数的显式关键字。默认情况下,所有一元参数化构造函数都应该是显式的。隐式构造函数会引发类似这样的歧义问题,并导致非常愚蠢、迂回的转换过程,这很容易导致有问题且效率非常低的代码
现在你已经准备好了,模糊问题解决了。没有显式构造函数,就无法防止这种歧义问题
对于客户端代码,您确实需要对其进行修改,以明确其转换:
V v;
const V cv;
fun2( I(v) );
fun2( CI(cv) );
fun( I(v) );
fun( CI(cv) );
现在构造I或CI对象需要这样的语法,但这是一件好事:再也没有人会意外地引入歧义问题了。很酷的问题,虽然我认为不可能阻止接受T的函数接受常数T.+1,因为它提出了一个问题,证明了显式构造函数的重要性以及与隐式构造函数相关的问题。谢谢你的回答。只需指出,我很清楚隐式转换(有效C++书籍、STL、Boost)的危险,但在这种情况下,转换是有意义的。I和CI模型范围,由成对迭代器组成的轻量级对象。不确定我是否会删除或保留隐式转换,并在需要时手动解决歧义(在上面的乐趣((I)(v)),或者只是在单独的行上创建I或CI并传递它们(或者使用方便的函数,如ref和cref作为boost reference wrapper)typedef只是别名。它们不创建单独的类型,所以歧义问题没有解决,您只是缺少它。@Study472,因此是问号。这真的值得否决票吗?哦,对不起,我是这个网站的新手,我不认为否决票会对评论员产生任何负面影响。我只是投了反对票,因为我知道这对KRao没有帮助,可能会让他更加困惑。如果它对你的地位有负面影响,我目前无法撤回否决票,因为时间已经过去,但如果你编辑帖子(任何轻微的改变都可以),我可以撤回它。