Templates 为什么可以';t我创建System::Collections::Generic::IEnumerable的模板化子类<;T>;? < >我想创建一个通用的IQueDebug实现,以便更容易封装一些本地C++类。当我尝试使用模板参数作为IEnumerable的参数来创建实现时,我得到了一个错误
下面是我提出的一个简单版本,它说明了我的问题:Templates 为什么可以';t我创建System::Collections::Generic::IEnumerable的模板化子类<;T>;? < >我想创建一个通用的IQueDebug实现,以便更容易封装一些本地C++类。当我尝试使用模板参数作为IEnumerable的参数来创建实现时,我得到了一个错误,templates,generics,c++-cli,Templates,Generics,C++ Cli,下面是我提出的一个简单版本,它说明了我的问题: 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>(); } ref类A{}; 模板 ref类测试:公共系统
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>();
}
ref类A{};
模板
ref类测试:公共系统::集合::泛型::IEnumerable//错误C3225。。。
{};
无效测试()
{
测试^a=gcnew测试();
}
在指示的行中,我得到以下错误:
错误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类父{};
ref类A{};
模板
ref类测试:公共父级//这里没有问题
{};
无效测试()
{
测试^a=gcnew测试();
}
我可以通过向实现类型添加另一个模板参数来解决此问题:
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^>>();
}
ref类A{};
模板
ref类测试:公共可枚举
{};
无效测试()
{
使用命名空间System::Collections::Generic;
测试^a=gcnew测试();
}
但这对我来说似乎很混乱。另外,我想了解一下这里发生了什么-为什么第一种方法不起作用?在第一个示例中,您的继承行应该是:
ref class Test : public System::Collections::Generic::IEnumerable<B>
Test<A^> ^a = gcnew Test<A^>();
ref类测试:公共系统::集合::通用::IEnumerable
(模板上没有参考标记)
那么您的用法行应该是:
ref class Test : public System::Collections::Generic::IEnumerable<B>
Test<A^> ^a = gcnew Test<A^>();
Test^a=gcnewtest();
引用标记位于模板的实例化中,而不是模板本身
这是您的示例,可编译:
using namespace System;
using namespace System::Collections::Generic;
ref class A {};
template<class B> ref class Test : public System::Collections::Generic::IEnumerable<B>
{
public:
B GetInstance()
{
return Activator::CreateInstance<B>();
}
virtual System::Collections::IEnumerator^ GetEnumeratorObj() =
System::Collections::IEnumerable::GetEnumerator
{
return nullptr;
}
virtual System::Collections::Generic::IEnumerator<B>^ GetEnumerator()
{
return nullptr;
}
};
void test()
{
Test<A^> ^a = gcnew Test<A^>();
}
使用名称空间系统;
使用命名空间System::Collections::Generic;
ref类A{};
模板引用类测试:公共系统::集合::泛型::IEnumerable
{
公众:
B GetInstance()
{
返回激活器::CreateInstance();
}
虚拟系统::集合::IEnumerator^GetEnumeratorObj()=
系统::集合::IEnumerable::GetEnumerator
{
返回空ptr;
}
虚拟系统::集合::泛型::IEnumerator^GetEnumerator()
{
返回空ptr;
}
};
无效测试()
{
测试^a=gcnew测试();
}
编辑:意识到我应该解释这是为什么。据我所知,不能在IEnumerable继承中指定B^的原因是IEnumerable是一个带有约束的泛型,而B是一个不受约束的模板参数。模板允许更灵活的语法,即使在它们管理ref对象时也是如此,因为即使在C++/CLI中,它们仍然是有效的“解析文本”。然而,当他们遇到带有约束的泛型时,规则会变得更加严格。谢谢,这解决了最初的问题。不过,我遗漏了部分问题——我还想在测试类中创建B的新实例。对于您的解决方案,gcnew B()会失败,因为B是一种句柄类型,有办法解决吗?是的,尽管这一点都不直观。使用激活器::CreateInstance()。我更新了上面的示例以进行演示。