我在 header 中有一个模板类无法编译,但是当我尝试制作一个最小的展示案例时,它可以正常编译。我正在尝试制作一个可以从数组构造的类,自动推导长度。错误是“对大小为零的数组的引用是非法的”,这是没有意义的,因为它应该通过模板自动推导长度。
相关代码:
template<class _Elem, bool _Null=true, bool _Trunc=false, class _Traits = std::char_traits<char>>
class basic_estring {
public:
typedef typename _Traits::pos_type size_type;
typedef typename _Elem value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
static const size_type npos;
basic_estring(const_pointer ptr, size_type capacity=npos, size_type used=npos);
template<int capacity> basic_estring(value_type (&data)[capacity], size_type used=npos);
// several hundred lines of other declarations
};
template<class _Elem, bool _Null, bool _Trunc, class _Traits>
basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(
typename basic_estring<_Elem,_Null,_Trunc,_Traits>::const_pointer ptr,
typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type capacity,
typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type used)
{} //This constructor has no problems (and all the others too)
template<class _Elem, bool _Null, bool _Trunc, class _Traits> template<int capacity>
basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(
typename basic_estring<_Elem,_Null,_Trunc,_Traits>::value_type (&data)[capacity], //LINE 218
typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type used)
{} //LINE 228
//several hundred lines of definitions
来自 MSVC C++ 2010 的错误:
1>/*snip*/\estring.h(218): error C2265: 'abstract declarator' : reference to a zero-sized array is illegal
1>/*snip*/\estring.h(228): error C2244: 'basic_estring<_Elem,_Null,_Trunc,_Traits>::{ctor}' : unable to match function definition to an existing declaration
1> definition
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring<_Elem,_Null,_Trunc,_Traits>::value_type (&)[1],basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type)'
1> existing declarations
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const basic_estring<_Elem,_Null,_Trunc,_Traits> &&)'
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const basic_estring<_Elem,_Null,_Trunc,_Traits> &)'
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const std::basic_string<_Elem,_Traits,Alloc> &)'
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(_Elem (&)[capacity],_Traits::pos_type)'
1> 'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const _Elem *,_Traits::pos_type,_Traits::pos_type)'
有人知道我做错了什么吗?我通常很擅长解决自己的问题,但这让我感到难过。我从其他构造函数重写了它,但没有解决任何问题。
[编辑] 当这个项目中的非原型(prototype)代码是
int main() {
return 0;
}
(不包括函数定义)因此,据我所知,这不是实例化问题。当我注释掉这段代码时,我也一直在类内部注释掉代码,发现如果我注释掉成员函数原型(prototype) capacity
,错误就会消失。我的类不继承任何其他类。
void resize( size_type Count );
void resize( size_type Count, value_type Ch );
size_type capacity( ) const; //if this is commented, the error goes away.
void reserve( size_type Count );
现在我完全被难住了。 [/编辑]
最佳答案
似乎在您的代码中的某个地方,您将一个零大小的数组作为参数传递给您的构造函数,导致编译器尝试为匹配的 basic_estring
构造函数签名实例化一个模板,该函数签名将将 capacity
定义为 0
,然后将对零大小数组的引用传递给您的构造函数。换句话说,问题不在于您的构造函数声明,而在于您尝试实例化构造函数模板的特定版本的代码中的其他地方。
例如,这段代码将编译得很好:
#include <iostream>
template<typename T>
class A
{
T* array;
public:
template<int capacity>
A(T (&data)[capacity]) { std::cout << capacity << std::endl; }
};
int main()
{
int array[5];
A<int> b(array);
return 0;
}
另一方面,将 array
的声明更改为
int main()
{
int array[] = {};
A<int> b(array);
return 0;
}
不再编译。它无法从输入参数中推断出 capacity
的模板值。事实上,gcc
似乎也无法正确识别参数类型,因为错误显示为
prog.cpp: In function ‘int main()’:
prog.cpp:22: error: no matching function for call to ‘A<int>::A(int [0])’
prog.cpp:5: note: candidates are: A<int>::A(const A<int>&)
意味着 gcc
正在寻找某种类型的可用于类型转换的单参数构造函数,默认的编译器创建的复制构造函数是唯一可用的候选者,因为我从未声明过任何其他构造函数具有单个参数的构造函数。
所以你的构造函数模板声明/定义本身没问题,但如果你用零长度数组实例化它,那么参数类型不正确,模板就无法正确实例化。我首先要查找您的错误的地方是实例化您的 basic_estring
的地方,而不是想知道构造函数本身有什么问题。
关于c++ - 将模板 typedef 的数组传递给构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6797074/