将模板 typedef 数组传递给构造函数

发布于 2024-11-26 07:13:52 字数 3492 浏览 1 评论 0原文

我的标头中有一个模板类无法编译,但是当我尝试制作一个最小的展示案例时,它编译得很好。我正在尝试创建一个可以从数组构造的类,自动推导出长度。错误是“引用零大小的数组是非法的”,这是没有意义的,因为它应该通过模板自动推导出长度。
相关代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜清冷一曲。 2024-12-03 07:13:52

似乎在代码中的某个地方,您将一个零大小的数组作为参数传递给构造函数,导致编译器尝试实例化匹配的 basic_estring 构造函数签名的模板,该签名将定义 capacity0,然后将对零大小数组的引用传递给构造函数。换句话说,问题不在于您的构造函数声明,而在于您尝试实例化构造函数模板的特定版本的代码中的其他位置。

例如,这段代码可以很好地编译:

#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;
}

不再编译。它无法从输入参数中推断出容量的模板值。事实上,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 的位置,而不是想知道构造函数本身有什么问题。

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 define capacity as 0, 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:

#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;
}

On the other-hand changing the declaration of array to

int main()
{
    int array[] = {};
    A<int> b(array);

    return 0;
}

No 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 as

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>&)

meaning 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.

岁月静好 2024-12-03 07:13:52

我终于想通了。当类还具有成员函数 capacity 时,具有模板类型 capacity 的构造函数会失败。哎呀。当我将模板类型重命名为 Cap 时,问题就消失了

I finally figured it out. The constructor with a template type capacity was failing when the class also had a member function capacity. Whoops. Problem goes away when I rename with template type to Cap

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文