What's wrong with this code?

  • Follow


Is this legal C++03 code:

template <class T>
struct A
{
    template<class U>
    A(int, long)
    {
    }
};

int main()
{
    A<int> a(2, 3L);
}

I have tried compiling this with g++ 3.4.6:
-----------------------------------------------------------
A.cpp: In function `int main()':
A.cpp:12: error: no matching function for call to `A<int>::A(int, long
int)'
A.cpp:3: note: candidates are: A<int>::A(const A<int>&)

It fails on Comeau as well:
--------------------------------------
"ComeauTest.c", line 4: warning: template parameter "U" is not used in
declaring the
           parameter types of function template "A<T>::A"
      template<class U>
                     ^

"ComeauTest.c", line 12: error: no instance of constructor "A<T>::A
[with T=int]"
           matches the argument list
             The argument types that you used are: (int, long)
      A<int> a(2, 3L);
               ^



I don't really understand why this should not work. Is it really
necessary for typename U to play a role to select the correct
constructor?

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply shri314 5/10/2009 4:38:03 PM

On May 10, 4:38 pm, "shri...@gmail.com" <shri...@gmail.com> wrote:
> Is this legal C++03 code:
>
> template <class T>
> struct A
> {
>     template<class U>
>     A(int, long)
>     {
>     }
>
> };
>
> int main()
> {
>     A<int> a(2, 3L);
>
> }
>
> I have tried compiling this with g++ 3.4.6:
> -----------------------------------------------------------
> A.cpp: In function `int main()':
> A.cpp:12: error: no matching function for call to `A<int>::A(int, long
> int)'
> A.cpp:3: note: candidates are: A<int>::A(const A<int>&)
>
> It fails on Comeau as well:
> --------------------------------------
> "ComeauTest.c", line 4: warning: template parameter "U" is not used in
> declaring the
>            parameter types of function template "A<T>::A"
>       template<class U>
>                      ^
>
> "ComeauTest.c", line 12: error: no instance of constructor "A<T>::A
> [with T=int]"
>            matches the argument list
>              The argument types that you used are: (int, long)
>       A<int> a(2, 3L);
>                ^
>
> I don't really understand why this should not work. Is it really
> necessary for typename U to play a role to select the correct
> constructor?

Yes, since it still has to know what type U will be for the particular
call. Even if it's seemingly unused, there are many reasons why it
might matter - for example, if you have a local static variable inside
that constructor.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pavel 5/11/2009 5:13:34 AM


On May 11, 7:38 am, "shri...@gmail.com" <shri...@gmail.com> wrote:
>
> template <class T>
> struct A
> {
>     template<class U>
You did not use the typename U.
>     A(int, long)
How about try "A(int, U)" ?
>     {
>     }
>
> };
>
> int main()
> {
>     A<int> a(2, 3L);
>
> }


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Linlin 5/11/2009 5:40:03 AM

shri314@gmail.com wrote:
> template <class T>
> struct A
> {
>     template<class U>
>     A(int, long)
>     {
>     }
> };
> 
> int main()
> {
>     A<int> a(2, 3L);
> }

Question: what is 'U' in the above constructor call? If you can't tell, how
should the compiler?

> I don't really understand why this should not work. Is it really
> necessary for typename U to play a role to select the correct
> constructor?

No, generally not. However, if the type can not be inferred from the
parameters, it must be given explicitly. I haven't tested it, but I would
try

  A<int> a<...>(2, 3L);

...of course substituting '...' with some type.

Notes:
1. I don't think it matters in any way that A itself is a template, only
that the constructor is one.
2. The above solution sure works for a function:

   template<typename T> T default_value() { return T(); }
   // doesn't compile, T is unknown
   default_value();
   // works
   default_value<float>();

Uli

-- 
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ulrich 5/11/2009 8:40:51 AM

On May 11, 4:38 am, "shri...@gmail.com" <shri...@gmail.com> wrote:
> Is this legal C++03 code:
>
> template <class T>
> struct A
> {
>     template<class U>
>     A(int, long)
>     {
>     }
>
> };
>
> int main()
> {
>     A<int> a(2, 3L);
>
> }
>
> I have tried compiling this with g++ 3.4.6:
> -----------------------------------------------------------
> A.cpp: In function `int main()':
> A.cpp:12: error: no matching function for call to `A<int>::A(int, long
> int)'
> A.cpp:3: note: candidates are: A<int>::A(const A<int>&)
>
> It fails on Comeau as well:
> --------------------------------------
> "ComeauTest.c", line 4: warning: template parameter "U" is not used in
> declaring the
>            parameter types of function template "A<T>::A"
>       template<class U>
>                      ^
>
> "ComeauTest.c", line 12: error: no instance of constructor "A<T>::A
> [with T=int]"
>            matches the argument list
>              The argument types that you used are: (int, long)
>       A<int> a(2, 3L);
>                ^
>
> I don't really understand why this should not work. Is it really
> necessary for typename U to play a role to select the correct
> constructor?
>

Misconception:
Whenever we define any template function with same the name as that of
class, is a constructor.

Reality:
No that is not constructor. Constructor can never be template.

Reason:
For any specific class constructor is remain same

Here for A<T> [T=int] we can have several function template<class U> A
(int, long) for [U=Any type].

But we instantiating object from A<T> [T=int] with parameter as if
this class has such parameterized constructor. But in reality this
class has only two constructor default and copy constructor which
compiler given.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply mail 5/11/2009 9:40:01 AM

On May 11, 8:40 pm, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
> shri...@gmail.com wrote:
> > template <class T>
> > struct A
> > {
> >     template<class U>
> >     A(int, long)
> >     {
> >     }
> > };
> >
> > int main()
> > {
> >     A<int> a(2, 3L);
> > }
>
> Question: what is 'U' in the above constructor call? If you can't tell,
how
> should the compiler?
>
> > I don't really understand why this should not work. Is it really
> > necessary for typename U to play a role to select the correct
> > constructor?
>
> No, generally not. However, if the type can not be inferred from the
> parameters, it must be given explicitly. I haven't tested it, but I would
> try
>
>   A<int> a<...>(2, 3L);
>

First - thanks for answering my question. It is correct that compiler
can't tell what U is, but there seems to be no way to specify it
explicitly either. I have tried the code above - it turns out to be a
syntax error. I even unsuccessfully tried other combinations of
disambiguation with "template" keyword for disabiguation.

A<int> a<char>(2, 3L);

A.cpp: In function `int main()':
A.cpp:12: error: expected initializer before '<' token

Neither does this:
A<int>::A<int> a<char>(2, 3L);

Neither does this:
A<int>::template A<char> a(2, 3L);

And some more that I have not listed here.

> ..of course substituting '...' with some type.
>
> Notes:
> 1. I don't think it matters in any way that A itself is a template, only
> that the constructor is one.

This is true.

> 2. The above solution sure works for a function:
>
>    template<typename T> T default_value() { return T(); }
>    // doesn't compile, T is unknown
>    default_value();
>    // works
>    default_value<float>();
>

This sure works as expected for functions.

> Uli
>
> --
> Sator Laser GmbH
> Gesch�ftsf�hrer: Thorsten F�cking, Amtsgericht Hamburg HR B62 932
>


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply shri314 5/11/2009 3:00:37 PM

shri314@gmail.com wrote:
> On May 11, 8:40 pm, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
>> shri...@gmail.com wrote:
>>> template <class T>
>>> struct A
>>> {
>>>     template<class U>
>>>     A(int, long)
>>>     {
>>>     }
>>> };
>>>
>>> int main()
>>> {
>>>     A<int> a(2, 3L);
>>> }
>> Question: what is 'U' in the above constructor call? If you can't tell,
> how
>> should the compiler?
>>
>>> I don't really understand why this should not work. Is it really
>>> necessary for typename U to play a role to select the correct
>>> constructor?
>> No, generally not. However, if the type can not be inferred from the
>> parameters, it must be given explicitly. I haven't tested it, but I would
>> try
>>
>>   A<int> a<...>(2, 3L);
>>
> 
> First - thanks for answering my question. It is correct that compiler
> can't tell what U is, but there seems to be no way to specify it
> explicitly either. I have tried the code above - it turns out to be a
> syntax error. I even unsuccessfully tried other combinations of
> disambiguation with "template" keyword for disabiguation.

Judging by the following posts, it seems as if you may be there a long
time trying to find a way that works:

http://learningcppisfun.blogspot.com/2007/02/constructor-templates-and-explicit.html
http://www.cpptalk.net/how-do-i-pass-explicit-template-arguments-to-a-templated-con-vt11726.html

The relevant bit (from the first page) is:

"Here is a note from the C++ standards 2005 draft that is quite
self-explantory: (section 14.8.1 paragraph 7)

[NOTE]

[ Note: because the explicit template argument list follows the function
template name, and because conversion member function templates and
constructor member function templates are called without using a
function name, there is no way to provide an explicit template argument
list for these function templates. �end note ]"

Regards,
Stu

> A<int> a<char>(2, 3L);
> 
> A.cpp: In function `int main()':
> A.cpp:12: error: expected initializer before '<' token
> 
> Neither does this:
> A<int>::A<int> a<char>(2, 3L);
> 
> Neither does this:
> A<int>::template A<char> a(2, 3L);
> 
> And some more that I have not listed here.
> 
>> ..of course substituting '...' with some type.
>>
>> Notes:
>> 1. I don't think it matters in any way that A itself is a template, only
>> that the constructor is one.
> 
> This is true.
> 
>> 2. The above solution sure works for a function:
>>
>>    template<typename T> T default_value() { return T(); }
>>    // doesn't compile, T is unknown
>>    default_value();
>>    // works
>>    default_value<float>();
>>
> 
> This sure works as expected for functions.
> 
>> Uli
>>
>> --
>> Sator Laser GmbH
>> Gesch�ftsf�hrer: Thorsten F�cking, Amtsgericht Hamburg HR B62 932


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Stuart 5/12/2009 2:17:32 AM

On May 11, 6:40 pm, mail....@gmail.com wrote:
> On May 11, 4:38 am, "shri...@gmail.com" <shri...@gmail.com> wrote:
>
>
>
> > Is this legal C++03 code:
>
> > template <class T>
> > struct A
> > {
> >     template<class U>
> >     A(int, long)
> >     {
> >     }
>
> > };
>
> > int main()
> > {
> >     A<int> a(2, 3L);
>
> > }
>
> > I have tried compiling this with g++ 3.4.6:
> > -----------------------------------------------------------
> > A.cpp: In function `int main()':
> > A.cpp:12: error: no matching function for call to `A<int>::A(int, long
> > int)'
> > A.cpp:3: note: candidates are: A<int>::A(const A<int>&)
>
> > It fails on Comeau as well:
> > --------------------------------------
> > "ComeauTest.c", line 4: warning: template parameter "U" is not used in
> > declaring the
> >            parameter types of function template "A<T>::A"
> >       template<class U>
> >                      ^
>
> > "ComeauTest.c", line 12: error: no instance of constructor "A<T>::A
> > [with T=int]"
> >            matches the argument list
> >              The argument types that you used are: (int, long)
> >       A<int> a(2, 3L);
> >                ^
>
> > I don't really understand why this should not work. Is it really
> > necessary for typename U to play a role to select the correct
> > constructor?
>
> Misconception:
> Whenever we define any template function with same the name as that of
> class, is a constructor.
>
> Reality:
> No that is not constructor. Constructor can never be template.
>
> Reason:
> For any specific class constructor is remain same
>
> Here for A<T> [T=int] we can have several function template<class U> A
> (int, long) for [U=Any type].
>
> But we instantiating object from A<T> [T=int] with parameter as if
> this class has such parameterized constructor. But in reality this
> class has only two constructor default and copy constructor which
> compiler given.
>

Yes and no...

Of course a constructor *can* be a template like here (at least I have
never seen that fail - on a lot of compilers):

//----------->>>
template <class T>
struct A
{
  int a;
  template<class U>
  A(T t, U u)
  : a( t+u)
  {
  }
};

int main()
{
  A<int> a(2, 3L); // *implicit* constructor template call works
  return a.a;      // will return 5
}
//<<<-----------

What will not work is an *explicit* template constructor call like
//-----------
// A<int><long> a(2, 3L);
// A<int> a<long>(2, 3L);
// A<int> a.A<long>(2, 3L);
// ... or whatever idea else one might have
//-----------

Yes: not everything "look alike" is a real constructor.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply jaybus56 5/12/2009 6:27:21 AM

Stuart Golodetz wrote:
> [ Note: because the explicit template argument list follows the function
> template name, and because conversion member function templates and
> constructor member function templates are called without using a
> function name, there is no way to provide an explicit template argument
> list for these function templates. —end note ]"

Thanks for setting that clear, I wasn't sure about it. Anyway, the obvious
workaround is to use a function instead:

   class A {
     template<typename U>
     static A create(int, long) {
        // ...
     }
   };

   A a = A::create<float>(42, 0L);

HTH

Uli

-- 
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ulrich 5/13/2009 9:12:01 AM

8 Replies
93 Views

(page loaded in 0.108 seconds)

Similiar Articles:













7/22/2012 12:58:07 AM


Reply: