conflicting declaration in template static member

Discussion in 'C++' started by Michael Doubez, Mar 24, 2011.

  1. Hello,

    I have the following minimal code:

    template< class T >
    struct Foo {
    static int const N = T::size;
    static int values[N];
    };
    template< class T > int const Foo<T>::N;
    template< class T > int Foo<T>::values[Foo<T>::N] = {};

    struct Bar {
    enum { size = 42 } ;
    };

    int main() {
    Foo<Bar> f;
    return f.N;
    }

    Which yield under gcc (4.1.3 and 4.3.3):
    error: conflicting declaration 'int Foo<T>::values [Foo::N]
    error: 'Foo<T>::values' has a previous declaration as 'int
    Foo<T>::values [Foo<T>::N]'
    error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    class is not definition

    The compiler seems confused by the size because it accepts the code
    - if I replace the definition of N by:
    enum { N = T::size };
    - if I don't use N but T::size

    This code pass under Comeau online (not in codepad).

    Is this a compiler bug or is it expected behavior ?

    --
    Michael
     
    Michael Doubez, Mar 24, 2011
    #1
    1. Advertising

  2. Michael Doubez

    puppi Guest

    On Mar 24, 6:18 am, Michael Doubez <> wrote:
    > Hello,
    >
    > I have the following minimal code:
    >
    > template< class T >
    > struct Foo {
    >     static int const N = T::size;
    >     static int values[N];};
    >
    > template< class T > int const Foo<T>::N;
    > template< class T > int          Foo<T>::values[Foo<T>::N] = {};
    >
    > struct Bar {
    >     enum { size = 42 } ;
    >
    > };
    >
    > int main() {
    >     Foo<Bar> f;
    >     return f.N;
    >
    > }
    >
    > Which yield under gcc (4.1.3 and 4.3.3):
    > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > error: 'Foo<T>::values' has a previous declaration as 'int
    > Foo<T>::values [Foo<T>::N]'
    > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > class is not definition
    >
    > The compiler seems confused by the size because it accepts the code
    >    - if I replace the definition of N by:
    > enum { N = T::size };
    >   - if I don't use N but T::size
    >
    > This code pass under Comeau online (not in codepad).
    >
    > Is this a compiler bug or is it expected behavior ?
    >
    > --
    > Michael


    Well, under gcc 4.4.5 it compiles fine...
    Have you tried to remove the declaration/initialization pair:
    template< class T > int const Foo<T>::N;
    template< class T > int Foo<T>::values[Foo<T>::N] = {};
    Since they really aren't necessary, trying to remove them would be my
    first try.
     
    puppi, Mar 24, 2011
    #2
    1. Advertising

  3. Michael Doubez

    Paul Guest

    "Michael Doubez" <> wrote in message
    news:...
    > Hello,
    >
    > I have the following minimal code:
    >
    > template< class T >
    > struct Foo {
    > static int const N = T::size;
    > static int values[N];
    > };
    > template< class T > int const Foo<T>::N;
    > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    >
    > struct Bar {
    > enum { size = 42 } ;
    > };
    >
    > int main() {
    > Foo<Bar> f;
    > return f.N;
    > }
    >
    > Which yield under gcc (4.1.3 and 4.3.3):
    > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > error: 'Foo<T>::values' has a previous declaration as 'int
    > Foo<T>::values [Foo<T>::N]'
    > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > class is not definition
    >
    > The compiler seems confused by the size because it accepts the code
    > - if I replace the definition of N by:
    > enum { N = T::size };
    > - if I don't use N but T::size
    >

    There is no N in the template declration :
    template<class T >
     
    Paul, Mar 24, 2011
    #3
  4. On 24 mar, 11:42, puppi <> wrote:
    > On Mar 24, 6:18 am, Michael Doubez <> wrote:
    > > I have the following minimal code:

    >
    > > template< class T >
    > > struct Foo {
    > >     static int const N = T::size;
    > >     static int values[N];};

    >
    > > template< class T > int const Foo<T>::N;
    > > template< class T > int          Foo<T>::values[Foo<T>::N] = {};

    >
    > > struct Bar {
    > >     enum { size = 42 } ;

    >
    > > };

    >
    > > int main() {
    > >     Foo<Bar> f;
    > >     return f.N;

    >
    > > }

    >
    > > Which yield under gcc (4.1.3 and 4.3.3):
    > > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > > error: 'Foo<T>::values' has a previous declaration as 'int
    > > Foo<T>::values [Foo<T>::N]'
    > > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > > class is not definition

    >
    > > The compiler seems confused by the size because it accepts the code
    > >    - if I replace the definition of N by:
    > > enum { N = T::size };
    > >   - if I don't use N but T::size

    >
    > > This code pass under Comeau online (not in codepad).

    >
    > > Is this a compiler bug or is it expected behavior ?

    >
    > Well, under gcc 4.4.5 it compiles fine...


    Ok. I suppose this is a bug and it has since been fixed.

    > Have you tried to remove the declaration/initialization pair:
    > template< class T > int const Foo<T>::N;
    > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    > Since they really aren't necessary, trying to remove them would be my
    > first try.


    They are necessary.
    Otherwise you get UB and if used, you are likely to get link errors.

    --
    Michael
     
    Michael Doubez, Mar 24, 2011
    #4
  5. Michael Doubez

    Paul Guest

    "Michael Doubez" <> wrote in message
    news:...
    On 24 mar, 11:42, puppi <> wrote:
    > On Mar 24, 6:18 am, Michael Doubez <> wrote:
    > > I have the following minimal code:

    >
    > > template< class T >
    > > struct Foo {
    > > static int const N = T::size;
    > > static int values[N];};

    >
    > > template< class T > int const Foo<T>::N;
    > > template< class T > int Foo<T>::values[Foo<T>::N] = {};

    >
    > > struct Bar {
    > > enum { size = 42 } ;

    >
    > > };

    >
    > > int main() {
    > > Foo<Bar> f;
    > > return f.N;

    >
    > > }

    >
    > > Which yield under gcc (4.1.3 and 4.3.3):
    > > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > > error: 'Foo<T>::values' has a previous declaration as 'int
    > > Foo<T>::values [Foo<T>::N]'
    > > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > > class is not definition

    >
    > > The compiler seems confused by the size because it accepts the code
    > > - if I replace the definition of N by:
    > > enum { N = T::size };
    > > - if I don't use N but T::size

    >
    > > This code pass under Comeau online (not in codepad).

    >
    > > Is this a compiler bug or is it expected behavior ?

    >
    > Well, under gcc 4.4.5 it compiles fine...


    Ok. I suppose this is a bug and it has since been fixed.

    > Have you tried to remove the declaration/initialization pair:
    > template< class T > int const Foo<T>::N;
    > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    > Since they really aren't necessary, trying to remove them would be my
    > first try.


    They are necessary.
    Otherwise you get UB and if used, you are likely to get link errors.
    ---------------------------------------------------------------------------

    N is dependant on the template instanciation because:
    static int const N = T::size. /*This does not instanciate the template.*/

    The compiler cannot know what T::size refers to without a template
    instanciation, so you need:
    template< class T > int Foo<T>::values[Foo<T>::N]; /*Explicitly instaciate
    the template*/
    Note: afaik the ( ={} ) doesn't do anything and is not required.
    ok now it knows that N is T::size:
    static int values[N]; /* --- N is T::size. ---*/

    AFAICT you do not need:
    template< class T > int const Foo<T>::N; /* This is instanciated implicitly
    with Foo<Bar> f anyway*/


    HTH
     
    Paul, Mar 24, 2011
    #5
  6. On 24 mar, 19:07, "Paul" <> wrote:
    > "Michael Doubez" <> wrote in message
    >
    > news:...
    > On 24 mar, 11:42, puppi <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > On Mar 24, 6:18 am, Michael Doubez <> wrote:
    > > > I have the following minimal code:

    >
    > > > template< class T >
    > > > struct Foo {
    > > > static int const N = T::size;
    > > > static int values[N];};

    >
    > > > template< class T > int const Foo<T>::N;
    > > > template< class T > int Foo<T>::values[Foo<T>::N] = {};

    >
    > > > struct Bar {
    > > > enum { size = 42 } ;

    >
    > > > };

    >
    > > > int main() {
    > > > Foo<Bar> f;
    > > > return f.N;

    >
    > > > }

    >
    > > > Which yield under gcc (4.1.3 and 4.3.3):
    > > > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > > > error: 'Foo<T>::values' has a previous declaration as 'int
    > > > Foo<T>::values [Foo<T>::N]'
    > > > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > > > class is not definition

    >
    > > > The compiler seems confused by the size because it accepts the code
    > > > - if I replace the definition of N by:
    > > > enum { N = T::size };
    > > > - if I don't use N but T::size

    >
    > > > This code pass under Comeau online (not in codepad).

    >
    > > > Is this a compiler bug or is it expected behavior ?

    >
    > > Well, under gcc 4.4.5 it compiles fine...

    >
    > Ok. I suppose this is a bug and it has since been fixed.
    >
    > > Have you tried to remove the declaration/initialization pair:
    > > template< class T > int const Foo<T>::N;
    > > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    > > Since they really aren't necessary, trying to remove them would be my
    > > first try.

    >
    > They are necessary.
    > Otherwise you get UB and if used, you are likely to get link errors.
    > ---------------------------------------------------------------------------
    >
    > N is dependant on the template instanciation


    N is dependant on the template parameter.

    > because:
    > static int const N = T::size. /*This does not instanciate the template.*/


    This declare a static member of integral type taking its value from
    the template parameter.

    >
    > The compiler cannot  know what T::size refers to without a template
    > instanciation, so you need:
    > template< class T > int Foo<T>::values[Foo<T>::N];  /*Explicitly instaciate
    > the template*/


    It defines the static member. Nothing is instantiated.

    The only work done by the compiler at this point is syntax checking.

    > Note: afaik the ( ={} ) doesn't do anything and is not required.


    It initialise the values of the array to the default value (0 in this
    case).
    You are right, it is not truly needed since global variable are 0
    initialized by default; I use it out of habit.

    > ok now it knows that N is T::size:
    > static int values[N]; /* --- N is T::size. ---*/


    That is the buggy step, the compiler doesn't recognize the definition
    relatively to the declaration (irrelevantly of any instantiation).

    > AFAICT you do not need:
    >  template< class T > int const Foo<T>::N; /* This is instanciated implicitly
    > with Foo<Bar> f anyway*/


    No it is not implicity instanciated without a definition.
    It is true that I don't really need it, provided I don't take a
    reference to it: the compiler directly reuse the value specified at
    declaration time; but it is formally UB.

    --
    Michael
     
    Michael Doubez, Mar 24, 2011
    #6
  7. Michael Doubez

    Paul Guest

    "Michael Doubez" <> wrote in message
    news:...
    On 24 mar, 19:07, "Paul" <> wrote:
    > "Michael Doubez" <> wrote in message
    > > > template< class T >
    > > > struct Foo {
    > > > static int const N = T::size;
    > > > static int values[N];};

    >
    > > > template< class T > int const Foo<T>::N;
    > > > template< class T > int Foo<T>::values[Foo<T>::N] = {};

    >
    > > > struct Bar {
    > > > enum { size = 42 } ;

    >
    > > > };

    >
    > > > int main() {
    > > > Foo<Bar> f;
    > > > return f.N;

    >
    > > > }

    >
    > > > Which yield under gcc (4.1.3 and 4.3.3):
    > > > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > > > error: 'Foo<T>::values' has a previous declaration as 'int
    > > > Foo<T>::values [Foo<T>::N]'
    > > > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > > > class is not definition

    >
    > > > The compiler seems confused by the size because it accepts the code
    > > > - if I replace the definition of N by:
    > > > enum { N = T::size };
    > > > - if I don't use N but T::size

    >
    > > > This code pass under Comeau online (not in codepad).

    >
    > > > Is this a compiler bug or is it expected behavior ?

    >
    > > Well, under gcc 4.4.5 it compiles fine...

    >
    > Ok. I suppose this is a bug and it has since been fixed.
    >
    > > Have you tried to remove the declaration/initialization pair:
    > > template< class T > int const Foo<T>::N;
    > > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    > > Since they really aren't necessary, trying to remove them would be my
    > > first try.

    >
    > They are necessary.
    > Otherwise you get UB and if used, you are likely to get link errors.
    > ---------------------------------------------------------------------------
    >
    > N is dependant on the template instanciation


    --N is dependant on the template parameter.

    > because:
    > static int const N = T::size. /*This does not instanciate the template.*/


    --This declare a static member of integral type taking its value from
    --the template parameter.

    Yes you are correct but the next occurence of N is not a template:
    static int values[N];

    I meant this cannot be resolved until the template is instanciated. But this
    is all done by the compiler anyway. I was thinking about templates to much
    and missed the obvious non-template issue.

    template< class T >
    struct Foo{
    static int const N= T::size;
    //static int values[N];
    int arr[N];
    };

    The above would need exlicit instaciation if I was correct but it doesn't


    >
    > The compiler cannot know what T::size refers to without a template
    > instanciation, so you need:
    > template< class T > int Foo<T>::values[Foo<T>::N]; /*Explicitly instaciate
    > the template*/


    --It defines the static member. Nothing is instantiated.
    Yes it defines the static.

    --The only work done by the compiler at this point is syntax checking.
    I disagree with that, I think the template must be instanciated, by the
    compiler, to define N. But I'm not certain , I may be wrong.
    I think there is more instanciations created under the hood than meets the
    eye.


    > Note: afaik the ( ={} ) doesn't do anything and is not required.


    --It initialise the values of the array to the default value (0 in this
    --case).
    --You are right, it is not truly needed since global variable are 0
    --initialized by default; I use it out of habit.

    No I was wrong , I though the expression was an explicit template
    instanciation and it isn't.
    You are right this line defines the static array.


    > ok now it knows that N is T::size:
    > static int values[N]; /* --- N is T::size. ---*/


    --That is the buggy step, the compiler doesn't recognize the definition
    --relatively to the declaration (irrelevantly of any instantiation).

    Yes I see how this can be a complex step for the compiler. I'm not sure how
    a compiler implements this because it cannot know the value of N until is
    has created a template instanciation, I think.


    > AFAICT you do not need:
    > template< class T > int const Foo<T>::N; /* This is instanciated
    > implicitly
    > with Foo<Bar> f anyway*/


    --No it is not implicity instanciated without a definition.
    --It is true that I don't really need it, provided I don't take a
    --reference to it: the compiler directly reuse the value specified at
    --declaration time; but it is formally UB.

    How would taking a reference make any difference?

    Does the template make any differenece to if you just did:
    struct Foo{
    static int const N = 42;
    };
     
    Paul, Mar 25, 2011
    #7
  8. On 25 mar, 01:04, "Paul" <> wrote:
    > "Michael Doubez" <> wrote in message
    > On 24 mar, 19:07, "Paul" <> wrote:
    > > AFAICT you do not need:
    > > template< class T > int const Foo<T>::N; /* This is instanciated
    > > implicitly
    > > with Foo<Bar> f anyway*/

    >
    > --No it is not implicity instanciated without a definition.
    > --It is true that I don't really need it, provided I don't take a
    > --reference to it: the compiler directly reuse the value specified at
    > --declaration time; but it is formally UB.
    >
    > How would taking a reference make any difference?
    >
    > Does the template make any differenece to if you just did:
    > struct Foo{
    >     static int const N = 42;
    > };


    Try it out:
    #include <iostream>

    struct Foo
    {
    // link fails with this line
    static int const N = 42;
    // compiles with this line
    // enum { N = 42 };
    };


    void print( int const & v ) {
    std::cout<<v<<'\n';
    }

    int main() {
    print(Foo::N);
    }

    --
    Michael
     
    Michael Doubez, Mar 25, 2011
    #8
  9. Michael Doubez

    Paul Guest

    "Michael Doubez" <> wrote in message
    news:...
    >On 25 mar, 01:04, "Paul" <> wrote:
    >> "Michael Doubez" <> wrote in message
    >> On 24 mar, 19:07, "Paul" <> wrote:
    >> > AFAICT you do not need:
    >> > template< class T > int const Foo<T>::N; /* This is instanciated
    >> > implicitly
    >> > with Foo<Bar> f anyway*/

    >>
    >> --No it is not implicity instanciated without a definition.
    >> --It is true that I don't really need it, provided I don't take a
    >> --reference to it: the compiler directly reuse the value specified at
    >> --declaration time; but it is formally UB.
    >>
    >> How would taking a reference make any difference?
    >>
    >> Does the template make any differenece to if you just did:
    >> struct Foo{
    >> static int const N = 42;
    >> };

    >
    >Try it out:
    >#include <iostream>
    >struct Foo{
    > // link fails with this line
    > static int const N = 42;
    > // compiles with this line
    > // enum { N = 42 };
    >};
    >
    >void print( int const & v ) { std::cout<<v<<'\n';}
    >
    >int main() {
    > print(Foo::N);
    >}


    I did try it out after I posted, and it worked just fine, what compiler did
    you say to avoid again? :)
    Here's the code I posted , maybe that compile of yours isn't too good.

    struct Bar1 { enum { size = 42 } ;};
    struct Bar2 { enum { size = 52 } ;};

    template< class T >
    struct Foo{
    static int const N= T::size;
    static int values[N];
    public:
    Foo(){}
    template<typename U>
    void func(Foo<U>& para);
    };

    //template< class T > int const Foo<T>::N;
    template<class T> int Foo<T>::values[Foo<T>::N]={0};

    template<typename T>
    template<typename U>
    void Foo<T>::func(Foo<U>& para){
    std::cout<< "\nthis->N: \t" << this->N;
    std::cout<< "\nthat.N: \t" << para.N;
    }

    void funct(int const & r){
    std::cout<<"\nIn funct, value of parameter = " << r;
    }

    int main() {
    Foo<Bar1> f1;
    Foo<Bar2> f2;

    funct(f1.N);
    funct(f2.N);
    f1.func(f2);
    f2.func(f1);
    }


    I also tried another couple of ways to use it as a reference and all seemed
    to compile ok with Microsoft v14 command line compiler.

    And I don't think that version is too good because i have had problems with
    it compiling templates in the form of :
    template<template<class T> class U, classT>
    When I go onto my newer VS2010 these compile just fine , so that old command
    line compiler I've been using to test your code isn't the greatest but it
    seems to compile/link your code fine without
    template< class T > int const Foo<T>::N;


    HTH
     
    Paul, Mar 25, 2011
    #9
  10. On 25 mar, 11:07, "Paul" <> wrote:
    > "Michael Doubez" <> wrote in message
    > >On 25 mar, 01:04, "Paul" <> wrote:
    > >> "Michael Doubez" <> wrote in message
    > >> On 24 mar, 19:07, "Paul" <> wrote:
    > >> > AFAICT you do not need:
    > >> > template< class T > int const Foo<T>::N; /* This is instanciated
    > >> > implicitly
    > >> > with Foo<Bar> f anyway*/

    >
    > >> --No it is not implicity instanciated without a definition.
    > >> --It is true that I don't really need it, provided I don't take a
    > >> --reference to it: the compiler directly reuse the value specified at
    > >> --declaration time; but it is formally UB.

    >
    > >> How would taking a reference make any difference?

    >
    > >> Does the template make any differenece to if you just did:
    > >> struct Foo{
    > >> static int const N = 42;
    > >> };

    >
    > >Try it out:
    > >#include <iostream>
    > >struct Foo{
    > >    // link fails with this line
    > >    static int const N = 42;
    > >    // compiles with this line
    > >    // enum { N = 42 };
    > >};

    >
    > >void print( int const & v ) { std::cout<<v<<'\n';}

    >
    > >int main() {
    > >    print(Foo::N);
    > >}

    >
    > I did try it out after I posted, and it worked just fine, what compiler did
    > you say to avoid again?  :)

    [snip]
    > When I go onto my newer VS2010 these compile just fine , so that old command
    > line compiler I've been using to test your code isn't the greatest but it
    > seems to compile/link your code fine without
    > template< class T > int const Foo<T>::N;


    It doesn't compile on codepad (And comeau doesn't link so it is of no
    help here).
    It doesn't either on gcc (up to 4.3.3)

    The standard is quite clear on the subject with the one definition
    rule and a static data member is always a declaration within the class
    scope (§9.4.2/2)
    "The declaration of a /static/ data member in its class is not a
    definition [...].

    And more precisely §9.4.2/4:
    "If a static data member is of const integral or const enumeration
    type, its declaration in the class
    definition can specify a constant-initializer which shall be an
    integral constant expression (5.19). In that
    case, the member can appear in integral constant expressions. *The
    member shall still be defined in a namespace scope if it is used in
    the program* and the namespace scope definition shall not contain an
    initializer."

    This requirement still holds in the proposal for c++0x.

    It may be a compiler extension or perhaps they don't consider this as
    "used in the program" (the value is used but not the variable, it
    could make sense).

    --
    Michael
     
    Michael Doubez, Mar 25, 2011
    #10
  11. Michael Doubez

    Paul Guest

    "Michael Doubez" <> wrote in message
    news:...
    On 25 mar, 11:07, "Paul" <> wrote:
    >> "Michael Doubez" <> wrote in message
    >> >On 25 mar, 01:04, "Paul" <> wrote:
    >> >> "Michael Doubez" <> wrote in message
    >> >> On 24 mar, 19:07, "Paul" <> wrote:
    >> >> > AFAICT you do not need:
    >> >> > template< class T > int const Foo<T>::N; /* This is instanciated
    >> >> > implicitly
    >> >> > with Foo<Bar> f anyway*/

    >>
    >> >> --No it is not implicity instanciated without a definition.
    >> >> --It is true that I don't really need it, provided I don't take a
    >> >> --reference to it: the compiler directly reuse the value specified at
    >> >> --declaration time; but it is formally UB.

    >>
    >> >> How would taking a reference make any difference?

    >>
    >> >> Does the template make any differenece to if you just did:
    >> >> struct Foo{
    >> >> static int const N = 42;
    >> >> };

    >>
    >> >Try it out:
    >> >#include <iostream>
    >> >struct Foo{
    >> > // link fails with this line
    >> > static int const N = 42;
    >> > // compiles with this line
    >> > // enum { N = 42 };
    >> >};

    >>
    >> >void print( int const & v ) { std::cout<<v<<'\n';}

    >>
    >> >int main() {
    >> > print(Foo::N);
    >> >}

    >>
    >> I did try it out after I posted, and it worked just fine, what compiler
    >> did
    >> you say to avoid again? :)

    >[snip]
    >> When I go onto my newer VS2010 these compile just fine , so that old
    >> command
    >> line compiler I've been using to test your code isn't the greatest but it
    >> seems to compile/link your code fine without
    >> template< class T > int const Foo<T>::N;

    >
    >It doesn't compile on codepad (And comeau doesn't link so it is of no
    >help here).
    >It doesn't either on gcc (up to 4.3.3)
    >
    >The standard is quite clear on the subject with the one definition
    >rule and a static data member is always a declaration within the class
    >scope (§9.4.2/2)
    >"The declaration of a /static/ data member in its class is not a
    >definition [...].
    >
    >And more precisely §9.4.2/4:
    >"If a static data member is of const integral or const enumeration
    >type, its declaration in the class
    >definition can specify a constant-initializer which shall be an
    >integral constant expression (5.19). In that
    >case, the member can appear in integral constant expressions. *The
    >member shall still be defined in a namespace scope if it is used in
    >the program* and the namespace scope definition shall not contain an
    >initializer."
    >
    >This requirement still holds in the proposal for c++0x.
    >
    >It may be a compiler extension or perhaps they don't consider this as
    >"used in the program" (the value is used but not the variable, it
    >could make sense).


    It thats what it says then it must be true.

    It still compiles fine if I use it like this:
    funct(Foo<Bar1>::N);


    So amybe there is something wrong with my compiler then . :)
     
    Paul, Mar 25, 2011
    #11
  12. Michael Doubez

    James Kanze Guest

    On Mar 24, 2:03 pm, Michael Doubez <> wrote:
    > On 24 mar, 11:42, puppi <> wrote:
    > > On Mar 24, 6:18 am, Michael Doubez <> wrote:
    > > > I have the following minimal code:


    > > > template< class T >
    > > > struct Foo {
    > > > static int const N = T::size;
    > > > static int values[N];};


    > > > template< class T > int const Foo<T>::N;
    > > > template< class T > int Foo<T>::values[Foo<T>::N] = {};


    > > > struct Bar {
    > > > enum { size = 42 } ;
    > > > };


    > > > int main() {
    > > > Foo<Bar> f;
    > > > return f.N;
    > > > }


    > > > Which yield under gcc (4.1.3 and 4.3.3):
    > > > error: conflicting declaration 'int Foo<T>::values [Foo::N]
    > > > error: 'Foo<T>::values' has a previous declaration as 'int
    > > > Foo<T>::values [Foo<T>::N]'
    > > > error: declaration of 'int Foo<T>::values [Foo<T>::N]' outside of
    > > > class is not definition


    > > > The compiler seems confused by the size because it accepts the code
    > > > - if I replace the definition of N by:
    > > > enum { N = T::size };
    > > > - if I don't use N but T::size


    > > > This code pass under Comeau online (not in codepad).


    > > > Is this a compiler bug or is it expected behavior ?


    > > Well, under gcc 4.4.5 it compiles fine...


    > Ok. I suppose this is a bug and it has since been fixed.


    > > Have you tried to remove the declaration/initialization pair:
    > > template< class T > int const Foo<T>::N;
    > > template< class T > int Foo<T>::values[Foo<T>::N] = {};
    > > Since they really aren't necessary, trying to remove them would be my
    > > first try.


    > They are necessary.
    > Otherwise you get UB and if used, you are likely to get link errors.


    This may have been changed in more recent versions of the draft,
    but at least in the current standard, the problem is that
    template< class T > int const Foo<T>::N;
    is NOT a definition, but only a declaration. When defining data
    in this manner, the declaration is only a definition if it
    contains an initializer. You should probably try:
    template< class T > int const Foo<T>::N = T::size;
    (and drop the = T::size in the class definition).

    --
    James Kanze
     
    James Kanze, Mar 26, 2011
    #12
    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.
Similar Threads
  1. Replies:
    2
    Views:
    4,654
  2. Replies:
    4
    Views:
    1,084
    Richard Tobin
    Dec 12, 2006
  3. Michael.Z
    Replies:
    11
    Views:
    822
    Michael.Zhang
    May 11, 2008
  4. dentzigui
    Replies:
    8
    Views:
    4,718
    Seebs
    Nov 1, 2009
  5. Skybuck Flying
    Replies:
    5
    Views:
    667
    ImpalerCore
    Nov 29, 2011
Loading...

Share This Page