The size of the array of static template elements used in the method

I have a template class with a static member array and a method that requires the size of the array.

template <int i>
struct Foo {
    static int data[];
    static int size() {
        return sizeof(data) / sizeof(data[0]);
    }
};

      

I want to initialize the array differently for each specialization.

template <>
int Foo<0>::data[] = { 0, 1, 2 };

      

It works as long as I only use this in one cpp file. But how do you use it across multiple files?

If I put the initialization in the header, the link will not complete because:

multiple definition of `Foo<0>::data'

      

If I put it in one of the cpp files, the others won't compile because:

invalid application of ‘sizeof’ to incomplete type ‘int []’

      

I'm interested in a solution that doesn't change the array to std :: vector.

+3


source to share


3 answers


You can try including it in an unnamed namespace, this will provide internal linkage and bypass the multiple definition of `Foo <0> :: data '



namespace{
template <int i>
struct Foo {
    static int data[];
    static int size() {
        return sizeof(data) / sizeof(data[0]);
    }
};
}

      

0


source


If you leave the definition of the struct template in the header, you can force the instantiation of the template in the translation block in which you initialize the data and not use it using extern, like so:

// imp.cc: initialization and instantiation
template <>
int Foo<0>::data[] = { 0, 1, 2 };
template struct Foo<0>;

// main.cc: extern declaration and usage:
template<> extern int Foo<0>::size ();
... Foo<0>::size () ...

      



(I tested it with a small example and clang.)

0


source


This works for me:

foo.h:

#ifndef FOO_H
#define FOO_H

template <int i>
struct Foo {
    static int data[];
    static int size() {
        return sizeof(data) / sizeof(data[0]);
    }
};

#endif

      

Foo-0.h:

#ifndef FOO_0_H
#define FOO_0_H

#include "Foo.h"

// Provide declarations of the members for 0
template <> int Foo<0>::data[];
template <> int Foo<0>::size();

#endif

      

Foo-0.cpp:

#include "Foo-0.h"

// Define the members for 0
template <> int Foo<0>::data[] = {10, 20, 30};
template <> int Foo<0>::size()
{
   return sizeof(data) / sizeof(data[0]);
}

      

main.cpp:

#include <iostream>

#include "Foo-0.h"

int main()
{
    std::cout << Foo<0>::data[0] << std::endl;
    std::cout << Foo<0>::size() << std::endl;
};

      

Output:

10
3

      

0


source







All Articles