给出以下代码:
#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
标志着所有这些都是错误的(这是触发我的
兴趣:你在滚动条中得到一个漂亮的红色标记
红色下划线的符号,但代码编译完美)。
换句话说:三个编译器和三个不同的行为。
(对于那些想知道原因的人:这是一个标准的习语 获取上下文 - 作业的左侧, 例如 - 参与重载决策。)
答案 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
标志。