在新的初始化序列存在的情况下,运算符重载解析如何工作?

时间:2014-02-17 18:05:41

标签: c++ c++11

给出以下代码:

#include <iostream>
#include <vector>

template <typename Source>
class ConvertProxy
{
    Source const* m_source;
public:
    ConvertProxy( Source const& source )
        : m_source( &source )
    {
    }

    template <typename Dest>
    operator Dest() const
    {
        return Dest(m_source->begin(), m_source->end());
    }
};

template <typename Source>
ConvertProxy<Source> convert( Source const& source )
{
    return ConvertProxy<Source>( source );
}

int
main()
{
    std::vector<int> src;
    for ( int i = 0; i != 5; ++ i ) {
        src.push_back( i );
    }
    std::vector<double> dest = convert( src );   /* XXX */
    for ( std::vector<double>::const_iterator i = dest.begin(), e = dest.end();
            i != e;
            ++ i ) {
        std::cout << *i << std::endl;
    }
    return 0;
}

在C ++ 11中是合法的,还是标记为XXX不明确的行?

同样的问题,但标记的行替换为:

std::vector<double> dest( convert( src ) );

std::vector<double> dest;
dest = convert( src );

在C ++之前的版本11中,我认为第二个是非法的,但另外两个是非法的 绝对不是。

FWIW:g ++(4.8.2)接受第一个,但不接受另外两个(带有 -std=c++11;否则它接受第一个和第三个,但是 不是第二个)。 VS 2013接受所有这些,但Intellisense 标志着所有这些都是错误的(这是触发我的 兴趣:你在滚动条中得到一个漂亮的红色标记 红色下划线的符号,但代码编译完美)。 换句话说:三个编译器和三个不同的行为。

(对于那些想知道原因的人:这是一个标准的习语 获取上下文 - 作业的左侧, 例如 - 参与重载决策。)

1 个答案:

答案 0 :(得分:0)

编译代码的一面有歧义,必须首先解决,我不认为C ++ 11标准添加了任何东西。

您应该使用容器的完整定义作为模板模板参数来匹配替换;最明确的一个是:

template <typename T, typename A, template <typename, typename> class Dest>
operator Dest<T, A>() const 
{ 
    return Dest<T, A>(m_source->begin(), m_source->end()); 
}

所有三个案例都编译,替换与

匹配
[T = double, A = allocator<double>, Dest = vector],

使用旧的gcc-4.1.2,并使用闪亮的新clang-3.4 - 带有和不带-std=c++11标志。