将模板 typedef 数组传递给构造函数
我的标头中有一个模板类无法编译,但是当我尝试制作一个最小的展示案例时,它编译得很好。我正在尝试创建一个可以从数组构造的类,自动推导出长度。错误是“引用零大小的数组是非法的”,这是没有意义的,因为它应该通过模板自动推导出长度。
相关代码:
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)'
有人知道我做错了什么吗?我通常很擅长解决自己的问题,但这让我难住了。我从其他构造函数重写了它,但没有解决任何问题。
[编辑] 当该项目中的非原型代码
int main() {
return 0;
}
(包括没有函数定义)时,错误仍然存在。因此,据我所知,这不是实例化问题。当我注释掉这段代码时,我也不断注释掉类内部的代码,并且发现如果我注释掉成员函数原型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 );
现在我完全被难住了。 [/编辑]
I have a template class in a header that fails to compile, but when I try to make a minimal show case, it compiles fine. I'm trying to make a class that can be constructed from an array, deducing the length automatically. The error is "reference to a zero-sized array is illegal", which makes no sense, as it should automatically deduce the length via the template.
Related Code:
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
And the error from 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)'
Anyone know what I'm doing wrong? I'm usually pretty good about solving my own problems, but this has me stumped. I rewrote it from the other constructors, and that solved nothing.
[Edit] The error is still there when the non-prototype code in this project is
int main() {
return 0;
}
(including no function definitions) So, it isn't an instantiation problem as far as I can tell. While I was commenting out this code, I kept commenting out code from inside the class too, and discovered that if I commented out the member function prototype capacity
, the error goes away. My class does not inherit from any other classes.
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 );
Now I'm totally stumped.
[/Edit]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
似乎在代码中的某个地方,您将一个零大小的数组作为参数传递给构造函数,导致编译器尝试实例化匹配的
basic_estring
构造函数签名的模板,该签名将定义capacity
为0
,然后将对零大小数组的引用传递给构造函数。换句话说,问题不在于您的构造函数声明,而在于您尝试实例化构造函数模板的特定版本的代码中的其他位置。例如,这段代码可以很好地编译:
另一方面,将
array
的声明更改为不再编译。它无法从输入参数中推断出容量的模板值。事实上,gcc 似乎也无法正确识别参数类型,因为错误表明
gcc 正在寻找某种类型的单参数构造函数可用于类型转换,默认编译器创建的复制构造函数是唯一可用的候选构造函数,因为我从未使用单个参数声明任何其他构造函数。
因此,您的构造函数模板声明/定义本身没问题,但如果您使用零长度数组实例化它,则参数类型不正确,并且模板无法正确实例化。我首先要查找错误的地方是实例化
basic_estring
的位置,而不是想知道构造函数本身有什么问题。It seems somewhere in your code you are passing in a zero-sized array as an argument to your constructor, causing the compiler to attempt to instantiate a template for the matching
basic_estring
constructor function signature that would definecapacity
as0
, and in-turn pass a reference to a zero-sized array to your constructor. In other words the problem is not your constructor declaration, but is somewhere else in your code where you are attempting to instantiate a specific version of the constructor template.For instance, this code will compile just fine:
On the other-hand changing the declaration of
array
toNo longer compiles. It can't deduce the template value for
capacity
from the input parameters. In fact,gcc
can't seem to correctly identify the argument type either, as the error comes out asmeaning that
gcc
is looking for some type of single-argument constructor that can be used for type conversion, with the default compiler-created copy constructor being the only available candidate since I never declared any other constructors with single arguments.So your constructor template declaration/definition itself is fine, but if you are instantiating it with a zero-length array, then the argument type is incorrect, and the template can't be properly instantiated. The first place I'd look for your error is where your
basic_estring
is being instantiated, rather than wondering what is wrong with the constructor itself.我终于想通了。当类还具有成员函数
capacity
时,具有模板类型capacity
的构造函数会失败。哎呀。当我将模板类型重命名为Cap
时,问题就消失了I finally figured it out. The constructor with a template type
capacity
was failing when the class also had a member functioncapacity
. Whoops. Problem goes away when I rename with template type toCap