1

I'm having a heck of a time trying to provide an out-of-line constructor for a nested class when the outer class has template parameters. The twist is the inner class only differs by data member declarations. Below is my MCVE. My apologies if it could be more minimal.

typedef unsigned char byte;

template<class W, bool B>
struct F
{
    struct G;
};

template class F<int, false>;
template class F<long, true>;

template<>
struct F<int, false>::G
{
    G();
    byte b[4];
};

template<>
struct F<long, true>::G
{
    G();
    byte b[6];
};

template<>
F<int, false>::G::G()
{
    b[0] = b[1] = b[2] = b[3] = 0;
}

template<>
F<long, true>::G::G()
{
    b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = 0;
}

int main(int argc, char* argv[])
{
    return 0;
}

From above, I simply want F::G::G to be out of line.

When I attempt to compile it, it results in:

test.cxx:29:1: error: template-id ‘G<>’ for ‘F<int, false>::G::G()’ does not match any template declaration
 F<int, false>::G::G()
 ^
test.cxx:35:1: error: template-id ‘G<>’ for ‘F<long int, true>::G::G()’ does not match any template declaration
 F<long, true>::G::G()
 ^

How do I provide an out-of-line constructor for G?


There are other similar questions that focus on functions. My disconnect seems to be getting this working when the data member is the sore spot.


Here's what I am trying to do. C++ does not allow it to be this easy, so I had to resort to template specializations to get the compile time declarations.

template<class W, bool B>
struct F
{
    struct G
    {
    #if (B == true)
        byte b[6];
    #else
        byte b[4];
    #endif
    };
};
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

1

Even though G is an inner class of a template class, it's not actually itself a template class.

This will work:

F<int, false>::G::G()
{
    b[0] = b[1] = b[2] = b[3] = 0;
}

F<long, true>::G::G()
{
    b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = 0;
}

of course in this case, you could save yourself the bother of worrying about constructors:

template<>
struct F<int, false>::G
{
    byte b[4] = { 0 };  // zero - initialised
};

template<>
struct F<long, true>::G
{
    byte b[6] = { 0 }; // zero - initialised
};
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • Thank you very much. I actually went the other way - trying to further template `G`, and C++ silliness like `template<> template<> ...`. I could scream at how much time I wasted on that.... – jww Apr 13 '16 at 13:21