下面的代码是我问题的最小例子。我创建了一个包含固定大小数组的简单模板类,并重载赋值操作符以接受定义方法size()和begin() (例如,initializer_lists)的任何类。我不明白为什么g++不能解决我打给这个接线员的电话(我用gcc 4.6):
***.cpp: In function ‘int main()’:
***.cpp:46:22: error: no match for ‘operator=’ in ‘a = {42, -1.0e+0, 3.14158999999999988261834005243144929409027099609375e+0}’
***.cpp:46:22: note: candidates are:
***.cpp:23:8: note: template<class U> A<T, N>::self& A::operator=(const U&) [with U = U, T = double, unsigned int N = 3u, A<T, N>::self = A<double, 3u>]
***.cpp:8:7: note: A<double, 3u>& A<double, 3u>::operator=(const A<double, 3u>&)
***.cpp:8:7: note: no known conversion for argument 1 from ‘<brace-enclosed initialiser list>’ to ‘const A<double, 3u>&’
***.cpp:8:7: note: A<double, 3u>& A<double, 3u>::operator=(A<double, 3u>&&)
***.cpp:8:7: note: no known conversion for argument 1 from ‘<brace-enclosed initialiser list>’ to ‘A<double, 3u>&&’第一个候选列表是正确的,但是没有关联的错误消息。以下是代码:
#include <iostream>
#include <algorithm>
#include <initializer_list>
// ------------------------------------------------------------------------
template <typename T, unsigned N>
class A
{
public:
typedef A<T,N> self;
// Default ctor
A() {}
// Copy ctor
template <typename U>
A( const U& other ) { operator=(other); }
// Assignemnt
template <typename U>
self& operator= ( const U& other )
{
if ( other.size() == N )
std::copy_n( other.begin(), N, m_data );
return *this;
}
// Display contents
void print() const
{
for ( unsigned i = 0; i < N; ++i )
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
private:
T m_data[N];
};
// ------------------------------------------------------------------------
int main()
{
A<double,3> a;
a = {42,-1.0,3.14159};
a.print();
}有人知道为什么这可能是模棱两可的,或者我做错了什么吗?
注意:理想情况下,我甚至希望用一个A<double,3> a = {42,-1.0,3.14159};替换主程序的前两行,但我不确定如何做,我目前得到了以下错误:
***: In function ‘int main()’:
***:45:34: error: could not convert ‘{42, -1.0e+0, 3.14158999999999988261834005243144929409027099609375e+0}’ from ‘<brace-enclosed initialiser list>’ to ‘A<double, 3u>’发布于 2014-04-20 20:01:16
与auto不同,在这种情况下,带括号的列表被推导为initializer_list,模板参数演绎则认为它是一个非推导的上下文,除非存在相应的initializer_list<T>类型的参数,在这种情况下,可以推导出T。
从第14.8.2.1/1节temp.deduct.call (重点后加)
模板参数推断是通过比较每个函数模板参数类型(称为
P)和调用的相应参数类型(称为A)来完成的,如下所述。如果从P中删除引用和cv-限定符给出了某些P0的std::initializer_list<P0>,并且参数是一个初始化程序列表(8.5.4),则对初始化程序列表中的每个元素执行扣减,将P0作为函数模板参数类型,并将初始化器元素作为其参数。否则,初始化器列表参数将导致参数被视为非推导的上下文 (14.8.2.5)。
因此,您的operator=的参数不会被推断为initializer_list<double>。要使代码工作,您必须定义一个接受operator=参数的initializer_list。
template <typename U>
self& operator= ( const std::initializer_list<T>& other )
{
if ( other.size() == N )
std::copy_n( other.begin(), N, m_data );
return *this;
}发布于 2014-04-20 19:57:39
大括号括起来的初始化程序列表不一定具有std::initializer_list<T>类型,因此需要指定赋值运算符模板需要一个std::initializer_list。
template <typename U>
A& operator=(std::initializer_list<U> other )
{
if ( other.size() == N )
std::copy_n( other.begin(), N, m_data );
return *this;
}或
A& operator=(std::initializer_list<double> other )
{
if ( other.size() == N )
std::copy_n( other.begin(), N, m_data );
return *this;
}我必须说,如果大小不匹配,那么一个赋值操作符就会悄然失败,这似乎不是一个好主意。
发布于 2014-04-20 19:44:32
我得说是这样的:
A<double,3> a;
a = {42,-1.0,3.14159};您正在使用默认构造函数初始化a,然后尝试在已经初始化的对象上使用初始化程序列表--这会抱怨缺少适当的operator=重载。相反,试着:
A<double,3> a = {42,-1.0,3.14159};编辑:
您还没有定义所需的构造函数:
template <typename T, unsigned N>
class A
{
public:
A(std::initializer_list list) : m_data(list) {}
//...
}https://stackoverflow.com/questions/23186775
复制相似问题