简体   繁体   中英

How to get two templated classes implicitly convertible to one another

I have recently encountered a scenario which causes the Microsoft Visual Studio 2013 compiler to produce an internal error ( C1001: An internal error has occured in the compiler. ).

If we have the header file Foo.h :

#pragma once
#ifndef FOO_H
#define FOO_H

#include "Bar.h"

template <typename T>
class Foo {
public:
      operator Bar<T>() const
      {
          Bar<T> bar;

          for( unsigned int i = 0; i < 5; ++i )
               bar.m_tArray[i] = m_tArray[i];

          return bar;
      }

private:
      template <typename U>
      friend class Bar<U>;

      T m_tArray[5];
};

#endif // FOO_H

And Bar.h :

#pragma once
#ifndef BAR_H
#define BAR_H

#include "Foo.h"

template <typename T>
class Bar {
public:
      operator Foo<T>() const
      {
          Foo<T> foo;

          for( unsigned int i = 0; i < 5; ++i )
               foo.m_tArray[i] = m_tArray[i];

          return foo;
      }

private:
      template <typename U>
      friend class Foo<U>;

      T m_tArray[5];
};

#endif // BAR_H

I can then cause the error by instantiating either class, for instance:

int main() {
    Foo<int> foo;
}

I'm guessing the error is occurring because each class refers to the other's definition within it's own definition and so there is an infinite recursion depth; however, I'm not sure how to resolve this problem as I can only have templates defined inline; I can not declare them and then define them elsewhere (when both templates have been declared and the internals exposed to one another).

You have to use forward declaration for your template classes. Example:

template <typename T>
class Foo;

template <typename T>
class Bar {
      template <class U>
      friend class Foo;
public:
      operator Foo<T>() const
      {
          Foo<T> foo;

          for( unsigned int i = 0; i < 5; ++i )
               foo.m_tArray[i] = m_tArray[i];

          return foo;
      }

private:

      T m_tArray[5];
};

template <typename T>
class Foo {
      template <class U>
      friend class Bar;
public:
      operator Bar<T>() const
      {
          Bar<T> bar;

          for( unsigned int i = 0; i < 5; ++i )
               bar.m_tArray[i] = m_tArray[i];

          return bar;
      }

private:

      T m_tArray[5];
};


int main() {
    Foo<int> foo;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM