Search code examples
c++templatespartial-specialization

Partial Specialization for an Integral Constant vs a Type


Is it possible to specialize a template based on whether a template argument is either a type or an integral constant? Here's an example that doesn't compile but which illustrates the intent:

#include <cstdio>
#include <cstddef>

// tag struct
struct DynamicSize {};

template<class T, class Size>
class Container;

template<class T>
class Container<T, DynamicSize>
{
public:
    Container() {
        std::puts("dynamic size");
    }
};

template<class T, int Size>
class Container<T, Size>
{
public:
    Container() {
        std::puts("static size");
    }
};

int main(int argc, char* argv[]) {
    Container<char, 20> a;
    Container<char, DynamicSize> b;
}

The Eigen library has support for matrices of fixed size or runtime determined size and does something similar to this. The implementation there is that the template argument is always an integral constant and the dynamic tag is just a constant equal to -1 but I'm curious if there's another way.


Solution

  • I think the only way to do this is to have the Container template take a type parameter for the Size. Then it's the responsibility of the type to handle whether it's dynamic or static. I'm thinking any details specific to type of storage type could be confined to the struct types. Perhaps the following example is helpful.

    Example Code

    #include <iostream>
    
    struct DynamicSize
    {
        static const int size = -1;
    };
    
    template<int Size>
    struct FixedSize
    {
        static const int size = Size;
    };
    
    template<class T, class Size>
    class Container
    {
    public:
        Container()
        {
            std::cout << Size::size << "\n";
        }
    };
    
    int main()
    {
        Container<char, FixedSize<20>> a;
        Container<char, DynamicSize> b;
    
        return 0;
    }
    

    Example Output

    20
    -1
    

    Live Example