Edward J Brown
Edward J Brown

Reputation: 331

Templated static template members

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

Upvotes: 0

Views: 134

Answers (2)

Naios
Naios

Reputation: 1573

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

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145204

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;
}

Upvotes: 0

Related Questions