0
votes

Ok so I have a template class with a static member whose value can be derived from just one of the template parameters, rather than defining the value for every possible value of the second parameter enum is it possible to use another template to define once for all possible values?

Or better illustrated by the code below:

    enum Foo
{
    FOO,
    BAR
};

enum Bar {
    OOF,
    RAB
};

template<Foo foo, Bar bar>
class FooTemplate
{
public:
    static const int RESULT;
};


template<Foo foo, Bar bar>
const int FooTemplate<Foo::FOO, bar>::RESULT = int(bar);

template<Foo foo, Bar bar>
const int FooTemplate<Foo::BAR, bar>::RESULT = 0;

Attempting to compile produces the following compile errors:

C2086 'const int FooTemplate::RESULT': redefinition

C3860 template argument list following class template name must list parameters in the order used in template parameter list

2
Just have the same formal template parameters as you have for the class template.Cheers and hth. - Alf
@Cheersandhth.-Alf Thank you, that fixes one of the errors but leaves one and produces another. Any ideas?Edward J Brown
Remove const int from the second?erip
A partial specialization of a static data member may exist only if there exists an associated partial specialization of the class template itself, like here (though it's not a partial specialization, it's just a definition)Piotr Skotnicki
@erip That makes the compiler treat FooTemplate<Foo::BAR, bar>::RESULT like a typename???Edward J Brown

2 Answers

1
votes

You could try to simplify your code as followed:

#include <type_traits>

enum Foo {
    FOO,
    BAR
};

enum Bar {
    OOF,
    RAB
};

template<Foo /*foo*/, Bar /*bar*/>
struct FooValue;

template<Bar bar>
struct FooValue<Foo::FOO, bar>
    : std::integral_constant<int, bar> { };

template<Bar bar>
struct FooValue<Foo::BAR, bar>
    : std::integral_constant<int, 0> { };

template<Foo foo, Bar bar>
class FooTemplate
    : public FooValue<foo, bar>
{
};

Demo

0
votes

Not quite sure what you want because the example appears to be over-simplified, but at least as far as the example goes you can express it like this:

enum Foo
{
    foo,
    bar
};

enum Bar {
    oof,
    rab
};

template<Foo foo, Bar bar>
class FooTemplate
{
public:
    static const int result = (foo == Foo::foo? int(bar) : 0);
};

template<Foo f, Bar b>
const int FooTemplate<f, b>::result;

#include <iostream>
using namespace std;
auto main() -> int
{
    cout << FooTemplate<foo, oof>::result << endl;
    cout << FooTemplate<foo, rab>::result << endl;
    cout << FooTemplate<bar, oof>::result << endl;
    cout << FooTemplate<bar, rab>::result << endl;
}