Template instantiation conflict with function definition

Discussion in 'C++' started by Alessandro [AkiRoss] Re, May 13, 2009.

  1. Hello there!
    While developing a policy-based application, I tried a code like this
    one (which is real code).

    I'm using g++ 4.3.3, which gives me these errors:
    templ_error.cpp: In function ‘int main()’:
    templ_error.cpp:22: error: multiple parameters named ‘base’
    templ_error.cpp:23: error: request for member ‘exec’ in ‘test’, which
    is of non-class type ‘Test<Numeric<3>, Numeric<5> > ()(Numeric<3>,
    Numeric<5>)’

    But I can't understand where is the problem: it seems that g++ read my
    declaration of a variable as a function definition. Please tell me if
    I'm doing it wrong: I can't see the error.
    Here's the code of templ_error.cpp

    #include <iostream>

    using namespace std;

    template <typename A, typename B>
    struct Test {
    A a;
    B b;
    Test(A a_, B b_): a(a_), b(b_) {}
    void exec() { cout << "Executed!" << a() << "-" << b() <<"\n"; }
    };

    template <int X>
    struct Numeric {
    int base;
    Numeric(int base_): base(base_) {}
    int operator()() { return base + X; }
    };

    int main() {
    int base = 1;
    Test<Numeric<3>, Numeric<5> > test(Numeric<3>(base), Numeric<5>
    (base));
    test.exec();
    return 0;
    }


    ps. Also with g++ 4.1 gives errors: the only difference is that
    "multiple parameters name" is not present as it has introduced in gcc
    4.3.

    Any help is appreciated
    Thanks!

    Regards
     
    Alessandro [AkiRoss] Re, May 13, 2009
    #1
    1. Advertising

  2. Alessandro [AkiRoss] Re wrote:
    > Hello there!
    > While developing a policy-based application, I tried a code like this
    > one (which is real code).
    >
    > I'm using g++ 4.3.3, which gives me these errors:
    > templ_error.cpp: In function ‘int main()’:
    > templ_error.cpp:22: error: multiple parameters named ‘base’
    > templ_error.cpp:23: error: request for member ‘exec’ in ‘test’, which
    > is of non-class type ‘Test<Numeric<3>, Numeric<5> > ()(Numeric<3>,
    > Numeric<5>)’
    >
    > But I can't understand where is the problem: it seems that g++ read my
    > declaration of a variable as a function definition. Please tell me if
    > I'm doing it wrong: I can't see the error.
    > Here's the code of templ_error.cpp
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > template <typename A, typename B>
    > struct Test {
    > A a;
    > B b;
    > Test(A a_, B b_): a(a_), b(b_) {}
    > void exec() { cout << "Executed!" << a() << "-" << b() <<"\n"; }
    > };
    >
    > template <int X>
    > struct Numeric {
    > int base;
    > Numeric(int base_): base(base_) {}
    > int operator()() { return base + X; }
    > };
    >
    > int main() {
    > int base = 1;
    > Test<Numeric<3>, Numeric<5> > test(Numeric<3>(base), Numeric<5>
    > (base));


    The line above declares a function 'test' with two arguments, 'base' and
    'base'. The first argument is of type 'Numeric<3>', the second is of
    type 'Numeric<5>'. If you needed to construct an object 'test' of type
    'Test<...>', then you need to move your parentheses a bit:

    Test<Numeric<3>, Numeric<5> >
    test( ( Numeric<3> ) base, ( Numeric<5> )base );

    Notice that I put the types in parentheses making those C-style type
    cast expressions.

    > test.exec();


    This line in your original program tries to apply '.' to the function
    type, and that's what the second error message is about. Pay attention
    to what your compiler is telling you!

    > return 0;
    > }
    >
    >
    > ps. Also with g++ 4.1 gives errors: the only difference is that
    > "multiple parameters name" is not present as it has introduced in gcc
    > 4.3.


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 13, 2009
    #2
    1. Advertising

  3. Alessandro [AkiRoss] Re

    James Kanze Guest

    On May 13, 1:53 am, "Alessandro [AkiRoss] Re" <>
    wrote:

    > While developing a policy-based application, I tried a code
    > like this one (which is real code).


    > I'm using g++ 4.3.3, which gives me these errors:
    > templ_error.cpp: In function ‘int main()’:
    > templ_error.cpp:22: error: multiple parameters named ‘base’
    > templ_error.cpp:23: error: request for member ‘exec’ in ‘test’, which
    > is of non-class type ‘Test<Numeric<3>, Numeric<5> > ()(Numeric<3>,
    > Numeric<5>)’


    > But I can't understand where is the problem: it seems that g++
    > read my declaration of a variable as a function definition.


    That's because it is a function declaration.

    [...]
    > int main() {
    > int base = 1;
    > Test<Numeric<3>, Numeric<5> > test(Numeric<3>(base), Numeric<5> (base));


    This declares (not defines) a function taking a Numeric< 3 > and
    a Numeric< 5 > as arguments, and returning a Test< Numeric< 3 >,
    Numeric< 5 > >. If what you want is a variable of type Test<
    Numeric< 3 >, Numeric< 5 > >, initialized with a Numeric< 3 >
    and a Numeric< 5 >, you must do something to prevent the string
    "Numeric< 3 >( base )" (and "Numeric< 5 >( base )") from being
    taken as a declaration:

    Test< Numeric< 3 >, Numeric< 5 > >
    test( (Numeric< 3 >( base )),
    (Numeric< 5 >( base )) ) ;

    Note the extra parentheses: C++ syntax doesn't allow the
    declaration of a function parameter to be in parentheses, so the
    results can only be an expression.

    The fundamental problem is that "Numeric< 3 >( base )" can be
    parsed as either an expression or a declaration. In such cases,
    the rules of the language say that if a declaration is legal, it
    is parsed as a declaration. So you have to do something to
    create a context where a declaration would not be legal. My
    favorite solution is the above, because it is (I think) the most
    universally applicable. Other solutions would be to put the
    parentheses around the Numeric< 3 > (only works if there is
    exactly one argument), or to use copy initialization (doesn't
    work if the type being constructed doesn't support copy).

    This is sometimes known as C++'s most embarassing parse.
    Everyone gets caught out by it from time to time.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 13, 2009
    #3
  4. On 13 mai, 10:04, James Kanze <> wrote:
    > On May 13, 1:53 am, "Alessandro [AkiRoss] Re" <>
    > wrote:
    >
    > > While developing a policy-based application, I tried a code
    > > like this one (which is real code).
    > > I'm using g++ 4.3.3, which gives me these errors:
    > > templ_error.cpp: In function ‘int main()’:
    > > templ_error.cpp:22: error: multiple parameters named ‘base’
    > > templ_error.cpp:23: error: request for member ‘exec’ in ‘test’, which
    > > is of non-class type ‘Test<Numeric<3>, Numeric<5> > ()(Numeric<3>,
    > > Numeric<5>)’
    > > But I can't understand where is the problem: it seems that g++
    > > read my declaration of a variable as a function definition.

    >
    > That's because it is a function declaration.
    >
    >     [...]
    >
    > > int main() {
    > >     int base = 1;
    > >     Test<Numeric<3>, Numeric<5> > test(Numeric<3>(base), Numeric<5> (base));

    >
    > This declares (not defines) a function taking a Numeric< 3 > and
    > a Numeric< 5 > as arguments, and returning a Test< Numeric< 3 >,
    > Numeric< 5 > >.  

    [snip]
    > Note the extra parentheses: C++ syntax doesn't allow the
    > declaration of a function parameter to be in parentheses, so the
    > results can only be an expression.
    >
    > The fundamental problem is that "Numeric< 3 >( base )" can be
    > parsed as either an expression or a declaration.  In such cases,
    > the rules of the language say that if a declaration is legal, it
    > is parsed as a declaration.  So you have to do something to
    > create a context where a declaration would not be legal.

    [snip]
    > This is sometimes known as C++'s most embarrassing parse.
    > Everyone gets caught out by it from time to time.


    And I thought it was the necessary space in nested template :)
    list<vector<int>> -> list<vector<int> >

    --
    Michael
     
    Michael Doubez, May 13, 2009
    #4
    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. David
    Replies:
    2
    Views:
    283
    Michiel Salters
    May 13, 2004
  2. Fernando Cuenca
    Replies:
    4
    Views:
    2,529
    Gianni Mariani
    Sep 6, 2004
  3. ES Kim
    Replies:
    4
    Views:
    349
    ES Kim
    Apr 15, 2005
  4. charles cashion

    css conflict (or html conflict)

    charles cashion, Feb 18, 2009, in forum: HTML
    Replies:
    2
    Views:
    797
    charles cashion
    Feb 18, 2009
  5. hqin
    Replies:
    24
    Views:
    2,879
    Keith Thompson
    Jan 17, 2011
Loading...

Share This Page