当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ cli - c++-cli: Why does calling a generic function fail, when it calls another generic function?

问题描述:

The following code is the essential part of my program and class to reproduce the failure:

using namespace System;

generic <class T>

ref class gener

{

public:

void func1g (T value)

{

Console::WriteLine (value);

int iValue = static_cast<int>(value);

if (iValue <= 0) return;

func2 ();

}

void func2 ()

{

T value = (T)(Object^)0;

func1g (value);

}

};

int main()

{

gener<int>^ g = gcnew gener<int>;

int iValue = 1;

g->func1g (iValue); // <<=== System.TypeLoadException

return 0;

}

When calling func1g, I get a System.TypeLoadException. I just don't understand why.

Is it because func2 does not have a generic parameter?

Here's the full error message (in german, but it just says 'unhandled exception' and 'could not be loaded'; no details):

The equivalent code in C# works:

public class gener<T>

{

public void func1g(T value)

{

Console.WriteLine(value);

int iValue = Convert.ToInt32(value);

if (iValue <= 0) return;

func2();

}

public void func2()

{

T value = (T)(object)0;

func1g(value);

}

};

internal class Program

{

private static void Main()

{

gener<int> g = new gener<int>();

int iValue = 1;

g.func1g(iValue);

return;

}

}

EDIT

I found a kind of 'workaround', see my answer below, but I don't know why this works.

I would appreciate it if someone could explain me the reason of this failure and the function of the workaround.

EDIT 2

In case you want to reproduce this: I use VS 2008 SP1.

I hope that it's not again compiler related like my last issue, although I personally expect this to be very likely...

网友答案:

After some testing, I just found a solution to this specific problem:

I need to define func1g as follows:

generic <class T>
void func1g (T value)
{
  ...
}

But I don't understand why.
Both ways (the code in the question and this solution) compile fine, but the first way produces a runtime exception, see the post.

One problem is remaining:
Notice that func1g above is declared and defined at the same location!
My original code is separated into .h and .cpp like this:

generic <class T>
ref class gener
{
public:
  generic <class T>
  void func1g (T value);

  void func2 ()
  {
    T value = (T)(Object^)0;
    func1g (value);
  }
};

generic <class T>
void gener<T>::func1g (T value)
{
  Console::WriteLine (value);
  int iValue = static_cast<int>(value);
  if (iValue <= 0) return;
  func2 ();
}

Now the compiler complains about the cpp with error C2511: 'void gener<T>::func1g(T)': overloaded member function not found in 'gener<T>'

Therefore I continued playing around (it really was trial and error) and found a working solution, that I absolutely don't understand any more:

using namespace System;

generic <class T>
ref class gener
{
public:
  generic <class T2>
  void func1g (T2 value);

  void func2 ()
  {
    T value = (T)(Object^)0;
    func1g (value);
  }
};

generic <class T>
generic <class T2>
void gener<T>::func1g (T2 value)
{
  Console::WriteLine (value);
  int iValue = static_cast<int>(value);
  if (iValue <= 0) return;
  func2 ();
}

int main()
{
  gener<int>^ g = gcnew gener<int>;
  int iValue = 1;
  g->func1g (iValue);

  return 0;
}

Can someone explain this to me?
I actually didn't know that a double generic definition was possible.

网友答案:

This is C# code (BTW it's also broken in C# unless T is System.Int32 or System.Int32, you should be using default(T)), it's not reasonable in C++/CLI.

  void func2 ()
  {
      T value = (T)(object)0;
      func1g(value);
  }

Just because the C++/CLI compiler accepts the exact same code, does not mean it does the same thing!

object is a keyword in C#, I have no idea what macros you've added to C++/CLI to make it compile (normally, it won't), but the equivalent C++/CLI type is System::Object^ (note the handle).

Anyway, you just want a value-initialized item of type T, in C++ that's written as

T value{};
分享给朋友:
您可能感兴趣的文章:
随机阅读: