Search code examples
c++compiler-errorsstrategy-pattern

how to create a policy template that defines a fixed value type


I have a Visual Studio 2008 C++03 application where I supply a policy FooTraits to a class Foo.

struct FooTraits
{
    enum { FooVal = 1 };
};

template< typename traits >
class Foo
{
public:
    typedef typename traits::FooVal foo_val; // errors on this line

    void FooDo( UINT matrix[ foo_val ] ) { /*...*/ };
};

typedef Foo< FooTraits > Foot;

int main( int argc, char* argv[] )
{
    Foot f;
    UINT matrix[ Foot::foo_val ] = { /*...*/ };
    f.FooDo( matrix );
    return 0;
}

But, I get a whole series of compiler errors all on the typedef:

error C2146: syntax error : missing ';' before identifier 'foo_val'
error C2838: 'FooVal' : illegal qualified name in member declaration
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

What's the correct way to create a policy that defines a fixed value?


Solution

  • The enumberated values introduced by enum are not, themselves, types. But the enum itself is. Therefore, in:

    enum Dummy { FooVal = 1 };
    

    Dummy is the type, not FooVal. You can typedef Dummy, to wit:

    struct FooTraits
    {
        enum Dummy { FooVal = 1 };
    };
    
    /* ... */
    
    template< typename traits >
    class Foo
    {
    public:
        typedef typename traits::Dummy dummy;
      };
    

    But you can't typedef FooVal, because it's not a type. Trying to typedef FooVal would be like trying to do this:

    int foo = 42;
    typedef FooBar foo;
    

    ...which, of course, makes no sense.

    Here's your code, fixed:

    struct FooTraits
    {
        enum { FooVal = 1 };
    };
    
    template< typename traits >
    class Foo
    {
    public:
        void FooDo( unsigned matrix[ traits::FooVal] ) { matrix;/*...*/ };
    };
    
    typedef Foo< FooTraits > Foot;
    
    int main(  )
    {
        Foot f;
        unsigned matrix[ FooTraits::FooVal ] = { /*...*/ };
        f.FooDo( matrix );
        return 0;
    }