Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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):
enter image description here

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

like image 262
Tobias Knauss Avatar asked Jun 27 '26 20:06

Tobias Knauss


1 Answers

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.

like image 141
Tobias Knauss Avatar answered Jun 30 '26 18:06

Tobias Knauss



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!