为什么我不能创建 System::Collections::Generic::IEnumerable的模板化子类?
我想创建一个通用的 IEnumerable 实现,以便更轻松地包装一些本机 C++ 类。当我尝试使用模板参数作为 IEnumerable 的参数来创建实现时,出现错误。
这是我想出的一个简单版本,它演示了我的问题:
ref class A {};
template<class B>
ref class Test : public System::Collections::Generic::IEnumerable<B^> // error C3225...
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
在指定的行上,我收到此错误:
错误 C3225:“T”的泛型类型参数不能是“B ^”,它必须是值类型或引用类型的句柄
如果我使用不同的父类,我看不到问题:
template<class P>
ref class Parent {};
ref class A {};
template<class B>
ref class Test : public Parent<B^> // no problem here
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
我可以解决此问题通过向实现类型添加另一个模板参数来实现:
ref class A {};
template<class B, class Enumerable>
ref class Test : public Enumerable
{};
void test()
{
using namespace System::Collections::Generic;
Test<A, IEnumerable<A^>> ^a = gcnew Test<A, IEnumerable<A^>>();
}
但这对我来说似乎很混乱。另外,我只是想了解这里发生了什么 - 为什么第一种方法不起作用?
I want to create a generic IEnumerable implementation, to make it easier to wrap some native C++ classes. When I try to create the implementation using a template parameter as the parameter to IEnumerable, I get an error.
Here's a simple version of what I came up with that demonstrates my problem:
ref class A {};
template<class B>
ref class Test : public System::Collections::Generic::IEnumerable<B^> // error C3225...
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
On the indicated line, I get this error:
error C3225: generic type argument for 'T' cannot be 'B ^', it must be a value type or a handle to a reference type
If I use a different parent class, I don't see the problem:
template<class P>
ref class Parent {};
ref class A {};
template<class B>
ref class Test : public Parent<B^> // no problem here
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
I can work around it by adding another template parameter to the implementation type:
ref class A {};
template<class B, class Enumerable>
ref class Test : public Enumerable
{};
void test()
{
using namespace System::Collections::Generic;
Test<A, IEnumerable<A^>> ^a = gcnew Test<A, IEnumerable<A^>>();
}
But this seems messy to me. Also, I'd just like to understand what's going on here - why doesn't the first way work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的第一个示例中,您的继承行应为:(
模板上没有引用标记)
然后您的使用行应为:
引用标记位于模板的实例化中,而不是模板本身。
这是您的示例,可编译:
编辑:意识到我应该解释为什么会这样。据我所知,不能在 IEnumerable 继承中指定 B^ 的原因是 IEnumerable 是一个带有约束的泛型,而 B 是一个不受约束的模板参数。模板允许更灵活的语法,即使它们管理 ref 对象,因为即使在 C++/CLI 中,它们仍然是有效的“解析文本”。然而,当他们遇到有约束的泛型时,规则就会变得更加严格。
In your first example, your inheritance line should read:
(no reference marker on the template)
Then your usage line should read:
The reference markers go in the instantiation of the template, not the template itself.
Here's your sample, compilable:
Edit: Realized I should explain why this is. To the best of my understanding, the reason that you can't specify B^ in the IEnumerable inheritance is that IEnumerable is a generic with a constraint on it, while B is a template parameter which is unconstrained. Templates allow for much more flexible syntax, even when they govern ref objects, as they're still effectively "parsed text" even in C++/CLI. However, when they bump into generics with constraints, the rules get a lot tighter.