2016-06-10 6 views
1

У меня есть общий интерфейс, который имеет метод с другим общим типом. Ограничение метода должно допускать только типы, которые являются производными от общего типа класса. Я попытался следующий код и некоторые другие возможности, но никто не работал до сих пор:Общий метод с общим типом типа класса

generic <class ObjectType> 
public interface class IFoo 
{ 
public: 
    generic <class ObjectTypeInherited> where ObjectTypeInherited : ObjectType 
    ObjectTypeInherited Test(); 
}; 

public ref class Derived : IFoo<System::Object^> 
{ 
public: 
generic <class ObjectTypeInherited> where ObjectTypeInherited :  System::Object^ 
    virtual ObjectTypeInherited Test() 
    { 
     return ObjectTypeInherited(); 
    } 
}; 

int main(array<System::String ^> ^args) 
{ 
    auto derived = gcnew Derived(); 
    auto nullString = derived->Test<System::String^>(); 
    if (nullString == nullptr) 
      System::Console::WriteLine("Got a null string!"); 
    return 0; 
} 

Я получаю следующее сообщение об ошибке с моим кодом:

error C3766: 'Derived' must provide an implementation for the interface 

метод «ObjectTypeInherited IFoo :: Test (аннулируются)»

Если я изменить его на:

generic <class ObjectTypeInherited> where ObjectTypeInherited :  System::Object^ 

я получаю другую ошибку:

error C3284: the constraints for generic parameter 'ObjectTypeInherited' of function 'ObjectTypeInherited Derived::Test(void)' must match the constraints for generic parameter 'ObjectTypeInherited' of function 'ObjectTypeInherited IFoo<System::Object ^>::Test(void)' 

Кто-нибудь знает, как правильно реализовать это?

Edit: System :: Object^ и System :: String^ классы используются только в качестве примера. Обычно я использую 2 собственные классы реф как MyObject и MyDerivedObject: MyObject

+0

Незначительное исправление: Ваш пункт, где для 'метода Derived' должен быть' где ObjectTypeInherited: System :: Object', без '' ^, но по-прежнему дает те же «ограничения должны соответствовать» ошибка. Я не знаю, почему эта ошибка все еще существует. –

ответ

1

Прежде всего generic <class ObjectTypeInherited> where ObjectTypeInherited : System::Object^. должно быть generic <class ObjectTypeInherited> where ObjectTypeInherited : System::Object.

^ знак здесь.

И тут начинается самое интересное ...

Как-то C++\CLI компилятор не хочет понять, что класс не должен быть универсальным в целях реализации IFoo<ObjectType>::Test. Поэтому я создал обходной путь для этой странной проблемы.

Вы можете использовать System::Object вместо MyObjectType. Я использовал MyObjectType просто для удобства.

public ref class MyObjectType 
{ 
}; 

generic <class ObjectType> 
public interface class IFoo 
{ 
public: 
    generic <class ObjectTypeInherited> where ObjectTypeInherited : ObjectType 
    ObjectTypeInherited Test(); 
}; 

//All the magic is here. Somehow the C++\CLI compiler does not wish to 
//understand that the DerivedBase class does not have to be generic in order 
//to implement the IFoo<ObjectType>::Test. As you can see the Whatever type 
//name is never used. Although without it the compiler gives the C3284 
//error. 
generic <class Whatever> 
public ref class DerivedBase : public IFoo<MyObjectType^> 
{ 
public: 
    //Why not make use of explicit syntax just because we can. 
    generic <class ObjectTypeInherited> where ObjectTypeInherited : MyObjectType 
    virtual ObjectTypeInherited Test() = IFoo<MyObjectType^>::Test 
    { 
     return ObjectTypeInherited(); 
    } 
}; 

//In order to overcome the fake genericness of DerivedBase I provide 
//another successor. 
public ref class Derived : public DerivedBase<Object^> 
{ 
}; 

У меня нет каких-либо глубоких знаний либо компилятора Рослин или C++ \ CLI, но на мой взгляд это кажется ошибка.

Если я делаю то же самое с управляемым кодом на C#, он должен выглядеть так же просто, как это. И здесь я остановлюсь. Даже без какого-либо странного поведения компилятора управляемые объявления легче поддерживать на стороне C#, чем C++ \ CLI.

public class MyObjectType 
{ 
} 

public interface IFoo<ObjectType> 
{ 
    ObjectTypeInherited Test<ObjectTypeInherited>() where ObjectTypeInherited : ObjectType; 
} 

public class Derived : IFoo<MyObjectType> 
{ 
    //Explicit 
    ObjectTypeInherited IFoo<MyObjectType>.Test<ObjectTypeInherited>() 
    { 
     return null; 
    } 

    //Implicit 
    public ObjectTypeInherited Test<ObjectTypeInherited>() where ObjectTypeInherited : MyObjectType 
    { 
     return null; 
    } 
} 
+0

Это не работает для меня, так как я получаю следующую ошибку: ошибка C3225: аргумент универсального типа для «ObjectType» не может быть «System :: Object», это должен быть тип значения или дескриптор ссылочного типа – Cosmo

+0

Ваш # 1 неверно, что вызывает ошибку C3225 «должен быть тип значения или дескриптор ссылочного типа», как сказал Космо.Добавив '^', ваш код все еще дает ошибку C3284, ограничения Derived :: Test должны соответствовать ограничениям IFoo :: Test. –

+0

Это может быть проблема с версиями VS; какую версию Visual Studio вы используете? –