Invalid Template Argument?

Discussion in 'C++' started by Immortal Nephi, Aug 14, 2010.

  1. Why do I get compiler error message? It explains that I am not
    allowed to create variable in the template parameter, but constant
    variable is acceptable.
    How can I fix the error?

    c:\test_mycode.cpp(24) : error C2975: 'size' : invalid template
    argument for 'Test', expected compile-time constant expression
    c:\test_template.h(41) : see declaration of 'size'

    // Test_Template.h

    #if !defined( TEST_TEMPLATE_H )
    #define TEST_TEMPLATE_H

    enum Type {
    Sample_Type1,
    Sample_Type2
    };

    template< Type >
    struct Traits {
    };

    template<>
    struct Traits< Sample_Type1 > {
    static const int x;
    static const int y;
    };

    template<>
    struct Traits< Sample_Type2 > {
    static const int x;
    static const int y;
    };

    template< typename T, int size >
    class Test {
    };

    #endif // end macro !defined( TEST_TEMPLATE_H )


    // Test_Template.cpp

    #include "Test_Template.h"

    const int Traits< Sample_Type1 >::x = 1;
    const int Traits< Sample_Type1 >::y = 2;

    const int Traits< Sample_Type2 >::x = 10;
    const int Traits< Sample_Type2 >::y = 20;

    template
    class Test< int, Traits< Sample_Type1 >::x >;

    template
    class Test< int, Traits< Sample_Type2 >::x >;


    // main.cpp

    #include "Test_Template.h"

    const Type type = Sample_Type1;
    const int size = Traits< type >::x;

    int main() {
    // Test< int, size > test;
    Test< int, Traits< type >::x > test2;

    return 0;
    }
     
    Immortal Nephi, Aug 14, 2010
    #1
    1. Advertising

  2. On Aug 14, 6:15 pm, Victor Bazarov <> wrote:
    > On 8/14/2010 1:57 PM, Immortal Nephi wrote:
    >
    > >    Why do I get compiler error message?  It explains that I am not
    > > allowed to create variable in the template parameter, but constant
    > > variable is acceptable.
    > >    How can I fix the error?

    >
    > Try initializing your static integral consts right in their respective
    > class definitions (full 'Traits' template specializations), instead of
    > later.
    >
    >
    >
    >
    >
    >
    >
    > > c:\test_mycode.cpp(24) : error C2975: 'size' : invalid template
    > > argument for 'Test', expected compile-time constant expression
    > >          c:\test_template.h(41) : see declaration of 'size'

    >
    > > // Test_Template.h

    >
    > > #if !defined( TEST_TEMPLATE_H )
    > > #define TEST_TEMPLATE_H

    >
    > > enum Type {
    > >    Sample_Type1,
    > >    Sample_Type2
    > > };

    >
    > > template<  Type>
    > > struct Traits {
    > > };

    >
    > > template<>
    > > struct Traits<  Sample_Type1>  {
    > >    static const int x;

    >
    > Try writing
    >
    >      static const int x = 1;
    >
    > >    static const int y;
    > > };

    >
    > > template<>
    > > struct Traits<  Sample_Type2>  {
    > >    static const int x;

    >
    > And here (just in case)
    >
    >        static const int x = 2;
    >
    >
    >
    >
    >
    > >    static const int y;
    > > };

    >
    > > template<  typename T, int size>
    > > class Test {
    > > };

    >
    > > #endif // end macro !defined( TEST_TEMPLATE_H )

    >
    > > // Test_Template.cpp

    >
    > > #include "Test_Template.h"

    >
    > > const int Traits<  Sample_Type1>::x = 1;
    > > const int Traits<  Sample_Type1>::y = 2;

    >
    > > const int Traits<  Sample_Type2>::x = 10;
    > > const int Traits<  Sample_Type2>::y = 20;

    >
    > > template
    > > class Test<  int, Traits<  Sample_Type1>::x>;

    >
    > > template
    > > class Test<  int, Traits<  Sample_Type2>::x>;

    >
    > > // main.cpp

    >
    > > #include "Test_Template.h"

    >
    > > const Type type = Sample_Type1;
    > > const int size = Traits<  type>::x;

    >
    > > int main() {
    > > // Test<  int, size>  test;
    > >    Test<  int, Traits<  type>::x>  test2;

    >
    > >    return 0;
    > > }


    Not what I wanted, but I found another way. I made my source code to
    work without compiler errors. Thanks for your tip.
     
    Immortal Nephi, Aug 15, 2010
    #2
    1. Advertising

  3. Immortal Nephi <>, on 14/08/2010 16:38:25, wrote:

    > On Aug 14, 6:15 pm, Victor Bazarov<> wrote:
    >> On 8/14/2010 1:57 PM, Immortal Nephi wrote:
    >>
    >>> Why do I get compiler error message? It explains that I am not
    >>> allowed to create variable in the template parameter, but constant
    >>> variable is acceptable.
    >>> How can I fix the error?

    >>
    >> Try initializing your static integral consts right in their respective
    >> class definitions (full 'Traits' template specializations), instead of
    >> later.


    <snip original code and several Victor's tips>

    > Not what I wanted, but I found another way. I made my source code to
    > work without compiler errors. Thanks for your tip.


    So post it here to complete the thread, and anybody getting here looking
    for a solution to a similar problem will find the working code.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 15, 2010
    #3
  4. Immortal Nephi

    James Kanze Guest

    On Aug 15, 12:15 am, Victor Bazarov <> wrote:
    > On 8/14/2010 1:57 PM, Immortal Nephi wrote:
    >
    > > Why do I get compiler error message? It explains that I am not
    > > allowed to create variable in the template parameter, but constant
    > > variable is acceptable.
    > > How can I fix the error?


    > Try initializing your static integral consts right in their respective
    > class definitions (full 'Traits' template specializations), instead of
    > later.


    According to the standard, that shouldn't make a difference.
    (But it wouldn't surprise me if it did with some compilers.)

    --
    James Kanze
     
    James Kanze, Aug 17, 2010
    #4
  5. On 8/17/2010 5:03 AM, James Kanze wrote:
    > On Aug 15, 12:15 am, Victor Bazarov<> wrote:
    >> On 8/14/2010 1:57 PM, Immortal Nephi wrote:
    >>
    >>> Why do I get compiler error message? It explains that I am not
    >>> allowed to create variable in the template parameter, but constant
    >>> variable is acceptable.
    >>> How can I fix the error?

    >
    >> Try initializing your static integral consts right in their respective
    >> class definitions (full 'Traits' template specializations), instead of
    >> later.

    >
    > According to the standard, that shouldn't make a difference.
    > (But it wouldn't surprise me if it did with some compilers.)


    I don't speak good Standardese, so I usually rely on logic hoping that
    it was present in the Committee members' minds when the Standard was
    written. So, logically speaking, if I define and initialize a static
    classwide const not in the class definition but elsewhere, the compiler
    won't have the chance to see that value if I use the static const where
    a compile-time constant expression is expected. Example:

    ----------------------------------- translation unit bar.cpp
    struct foo { static const int size; }; // usually from a header

    int bar[foo::size]; // huh?
    ----------------------------------- translation unit foo.cpp
    struct foo { static const int size; }; // usually from a header

    static const foo::size = 42;
    ------------------------------------------------------------

    OTOH, if I do give the static some value right in the class definition,
    the compiler is free to use that value (and not the member) where it
    shows up in the code:

    ----------------------------------- translation unit bar.cpp
    struct foo { static const int size = 42; }; // usually from a header

    int bar[foo::size]; // success: using the *value* 42
    ----------------------------------- translation unit foo.cpp
    struct foo { static const int size; }; // usually from a header

    static const foo::size; // definition - just in case
    ------------------------------------------------------------

    IOW, IMNSHO it *does* make a difference.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Aug 17, 2010
    #5
  6. Immortal Nephi

    James Kanze Guest

    On Aug 17, 1:40 pm, Victor Bazarov <> wrote:
    > On 8/17/2010 5:03 AM, James Kanze wrote:


    > > On Aug 15, 12:15 am, Victor Bazarov<> wrote:
    > >> On 8/14/2010 1:57 PM, Immortal Nephi wrote:


    > >>> Why do I get compiler error message? It explains that I am not
    > >>> allowed to create variable in the template parameter, but constant
    > >>> variable is acceptable.
    > >>> How can I fix the error?


    > >> Try initializing your static integral consts right in their respective
    > >> class definitions (full 'Traits' template specializations), instead of
    > >> later.


    > > According to the standard, that shouldn't make a difference.
    > > (But it wouldn't surprise me if it did with some compilers.)


    > I don't speak good Standardese, so I usually rely on logic
    > hoping that it was present in the Committee members' minds
    > when the Standard was written.


    Regretfully, they don't always express themselves in standardese
    as clearly as one might wish.

    > So, logically speaking, if I define and initialize a static
    > classwide const not in the class definition but elsewhere, the
    > compiler won't have the chance to see that value if I use the
    > static const where a compile-time constant expression is
    > expected.


    Well, I think I may have misread the original code. I didn't
    see that several translation units were involved. But there is
    still one problem with your reasoning: I can follow it if
    I initialize the constant in another translation unit, or even,
    maybe after the actual use. But in the case in question, the
    variable was defined and initialized before actual use in the
    file. The compiler can easily see the value.

    > Example:
    >
    > ----------------------------------- translation unit bar.cpp
    > struct foo { static const int size; }; // usually from a header


    > int bar[foo::size]; // huh?


    Agreed. Read strictly, the standard requires this to
    work, provided foo::size is initialized with an integral
    constant expression where ever it happens to be defined. I'm
    pretty sure that this was not the intent, however, and no
    compiler implements it.

    > ----------------------------------- translation unit foo.cpp
    > struct foo { static const int size; }; // usually from a header
    >
    > static const foo::size = 42;


    (There's a static too many there. You meant "int const
    foo::size = 42;", I'm sure.)

    And here:

    int bar[foo::size];

    is (or should be) legal. The question becomes more interesting
    if foo is a template; I think it should still be legal, but
    I can imagine some compiler rejecting it, on the grounds that
    the definition might have been instantiated in some other
    translation unit, rather than this one.

    > ------------------------------------------------------------


    > OTOH, if I do give the static some value right in the class
    > definition, the compiler is free to use that value (and not
    > the member) where it shows up in the code:


    > ----------------------------------- translation unit bar.cpp
    > struct foo { static const int size = 42; }; // usually from a header


    > int bar[foo::size]; // success: using the *value* 42
    > ----------------------------------- translation unit foo.cpp
    > struct foo { static const int size; }; // usually from a header


    > static const foo::size; // definition - just in case
    > ------------------------------------------------------------


    > IOW, IMNSHO it *does* make a difference.


    The issue isn't whether you give the static the value in the
    class definition. It is whether the definition is visible, so
    the compiler can see it. And this issue really only affects
    templates:

    template<typename T>
    struct Foo
    {
    static int const i;
    };

    template<typename T>
    int Foo<T>::i = 42;

    int bar[Foo<int>::i];

    --
    James Kanze
     
    James Kanze, Aug 17, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page