Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #15117 > unrolled thread

Any way to defer template function overloading?

Started byQi <no@no.no>
First post2012-04-01 10:05 +0800
Last post2012-04-02 14:41 +0000
Articles 17 — 7 participants

Back to article view | Back to comp.lang.c++


Contents

  Any way to defer template function overloading? Qi <no@no.no> - 2012-04-01 10:05 +0800
    Re: Any way to defer template function overloading? Ian Collins <ian-news@hotmail.com> - 2012-04-01 16:06 +1200
      Re: Any way to defer template function overloading? Qi <no@no.no> - 2012-04-01 13:53 +0800
    Re: Any way to defer template function overloading? Juha Nieminen <nospam@thanks.invalid> - 2012-04-01 17:24 +0000
      Re: Any way to defer template function overloading? "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2012-04-02 00:40 +0200
        Re: Any way to defer template function overloading? Ian Collins <ian-news@hotmail.com> - 2012-04-02 11:02 +1200
        Re: Any way to defer template function overloading? Juha Nieminen <nospam@thanks.invalid> - 2012-04-02 05:29 +0000
      Re: Any way to defer template function overloading? Qi <no@no.com> - 2012-04-02 13:48 +0800
        Re: Any way to defer template function overloading? Ian Collins <ian-news@hotmail.com> - 2012-04-02 17:53 +1200
          Re: Any way to defer template function overloading? Qi <no@no.com> - 2012-04-02 13:57 +0800
            Re: Any way to defer template function overloading? Ian Collins <ian-news@hotmail.com> - 2012-04-02 18:12 +1200
              Re: Any way to defer template function overloading? Miles Bader <miles@gnu.org> - 2012-04-02 15:32 +0900
        Re: Any way to defer template function overloading? Miles Bader <miles@gnu.org> - 2012-04-02 14:58 +0900
        Re: Any way to defer template function overloading? Juha Nieminen <nospam@thanks.invalid> - 2012-04-02 10:11 +0000
          Re: Any way to defer template function overloading? Qi <no@no.com> - 2012-04-02 19:04 +0800
            Re: Any way to defer template function overloading? Qi <no@no.com> - 2012-04-02 19:17 +0800
    Re: Any way to defer template function overloading? jgk@panix.com (Joe keane) - 2012-04-02 14:41 +0000

#15117 — Any way to defer template function overloading?

FromQi <no@no.no>
Date2012-04-01 10:05 +0800
SubjectAny way to defer template function overloading?
Message-ID<jl8d4h$hbf$1@speranza.aioe.org>
Let me show some test code.

=====code start

template <typename T>
void abc(const T &)
{
	cout << "1" << endl;
}

template <typename T>
void test(const T & a)
{
	abc(a);
}

void abc(const string &)
{
	cout << "2" << endl;
}

int main(int argc, char * argv[])
{
	(void)argc;
	(void)argv;

	string s;
	test(s);
	
	return 0;
}

=====code end

"abc" is a template function that I use as some kind of traits.
(similar as get_pointer in Boost).
The "string" overloading is after the "test" function.

"test" is the function where using "abc". "test" is a template
function too.

"main" is the function that using "test". It's guaranteed that
all overloading will be declared before main (but may after "test").

In standard way, above code will print "1" on GCC (VC will print "2"
because of its less standard template parsing).

My question is, is there any way to make "test" chooses
the "string" overloading and print 2, no matter the overloading
is before or after "test"?

The reason I want that is, the overloading functions may spread
in multiple headers, if "test" can only choose the overloading
that declared before it, that will enforce the including order of
the headers.


Thanks


-- 
WQ

[toc] | [next] | [standalone]


#15118

FromIan Collins <ian-news@hotmail.com>
Date2012-04-01 16:06 +1200
Message-ID<9tq2ijFm3gU1@mid.individual.net>
In reply to#15117
On 04/ 1/12 02:05 PM, Qi wrote:
> Let me show some test code.
>
> =====code start
>
> template<typename T>
> void abc(const T&)
> {
> 	cout<<  "1"<<  endl;
> }
>
> template<typename T>
> void test(const T&  a)
> {
> 	abc(a);
> }
>
> void abc(const string&)
> {
> 	cout<<  "2"<<  endl;
> }
>
> int main(int argc, char * argv[])
> {
> 	(void)argc;
> 	(void)argv;

Why do this?

> 	string s;
> 	test(s);
> 	
> 	return 0;
> }
>
> =====code end
>
> "abc" is a template function that I use as some kind of traits.
> (similar as get_pointer in Boost).
> The "string" overloading is after the "test" function.
>
> "test" is the function where using "abc". "test" is a template
> function too.
>
> "main" is the function that using "test". It's guaranteed that
> all overloading will be declared before main (but may after "test").
>
> In standard way, above code will print "1" on GCC (VC will print "2"
> because of its less standard template parsing).
>
> My question is, is there any way to make "test" chooses
> the "string" overloading and print 2, no matter the overloading
> is before or after "test"?

Make the function a specialisation:

template <>
void abc(const std::string&)
{
   std::cout << "2" << std::endl;
}

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#15120

FromQi <no@no.no>
Date2012-04-01 13:53 +0800
Message-ID<jl8qgf$6bf$1@speranza.aioe.org>
In reply to#15118
On 2012-4-1 12:06, Ian Collins wrote:
>
> Make the function a specialisation:
>
> template <>
> void abc(const std::string&)
> {
> std::cout << "2" << std::endl;
> }

Awesome, it works perfectly. Thanks.

Can I understand that as, the specialization is solved
at the second pass of template parsing, while the overloading
is solved at the first pass?

However, here has some discussion on the risk to use
template function specialization
http://www.gotw.ca/publications/mill17.htm

Seems the class specialization way is better and safer. :-)


-- 
WQ

[toc] | [prev] | [next] | [standalone]


#15121

FromJuha Nieminen <nospam@thanks.invalid>
Date2012-04-01 17:24 +0000
Message-ID<4f788f56$0$4347$7b1e8fa0@news.nbl.fi>
In reply to#15117
Qi <no@no.no> wrote:
> int main(int argc, char * argv[])
> {
>        (void)argc;
>        (void)argv;

  This seemed like nonsensical code because it does nothing. Then I realized
that it's an ugly hack to silence the compiler warning about unused
variables. That's not how you do it.

  The proper way of getting rid of the warnings is to not name the
parameters. If you still want to have their names visible, you can
simply comment them out:

    int main(int /*argc, char** /*argv*/)
    {
        ...
    }

  Incidentally, main() doesn't need parameters, so you can just omit them:

    int main()
    {
        ...
    }

[toc] | [prev] | [next] | [standalone]


#15122

From"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>
Date2012-04-02 00:40 +0200
Message-ID<jlalgo$376$1@dont-email.me>
In reply to#15121
On 01.04.2012 19:24, Juha Nieminen wrote:
> Qi<no@no.no>  wrote:
>> int main(int argc, char * argv[])
>> {
>>         (void)argc;
>>         (void)argv;
>
>    This seemed like nonsensical code because it does nothing. Then I realized
> that it's an ugly hack to silence the compiler warning about unused
> variables. That's not how you do it.

Right. I used to advocate a function template for that. But now I'd 
rather use a macro, e.g. like this:


<code>
#if !defined( CPP_DECLARE_UNUSED )
#   define CPP_DECLARE_UNUSED( argName )    \
         (void)(argName, void(), 0); struct argName; (void)0
#endif
// SO user sehe: "(void)0" for semicolon
// SO user R. Martinho Fernandes, pointed out operator void() problem
// SO user Johannes Schaub, solution to operator,() problem
</code>


>    The proper way of getting rid of the warnings is to not name the
> parameters. If you still want to have their names visible, you can
> simply comment them out:
>
>      int main(int /*argc, char** /*argv*/)

But the names have documentary value, and those comments do not nest, 
e.g. for the purpose of commenting out code.


>      {
>          ...
>      }
>
>    Incidentally, main() doesn't need parameters, so you can just omit them:
>
>      int main()
>      {
>          ...
>      }

Yes. :-)


Cheers,

- Alf

[toc] | [prev] | [next] | [standalone]


#15123

FromIan Collins <ian-news@hotmail.com>
Date2012-04-02 11:02 +1200
Message-ID<9ts545FfaaU2@mid.individual.net>
In reply to#15122
On 04/ 2/12 10:40 AM, Alf P. Steinbach wrote:
> On 01.04.2012 19:24, Juha Nieminen wrote:
>> Qi<no@no.no>   wrote:
>>> int main(int argc, char * argv[])
>>> {
>>>          (void)argc;
>>>          (void)argv;
>>
>>     This seemed like nonsensical code because it does nothing. Then I realized
>> that it's an ugly hack to silence the compiler warning about unused
>> variables. That's not how you do it.
>
> Right. I used to advocate a function template for that. But now I'd
> rather use a macro, e.g. like this:
>
>
> <code>
> #if !defined( CPP_DECLARE_UNUSED )
> #   define CPP_DECLARE_UNUSED( argName )    \
>           (void)(argName, void(), 0); struct argName; (void)0
> #endif
> // SO user sehe: "(void)0" for semicolon
> // SO user R. Martinho Fernandes, pointed out operator void() problem
> // SO user Johannes Schaub, solution to operator,() problem
> </code>
>
>
>>     The proper way of getting rid of the warnings is to not name the
>> parameters. If you still want to have their names visible, you can
>> simply comment them out:
>>
>>       int main(int /*argc, char** /*argv*/)
>
> But the names have documentary value, and those comments do not nest,
> e.g. for the purpose of commenting out code.

So include the names in the function declaration, but not in the definition.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#15124

FromJuha Nieminen <nospam@thanks.invalid>
Date2012-04-02 05:29 +0000
Message-ID<4f79393e$0$4376$7b1e8fa0@news.nbl.fi>
In reply to#15122
Alf P. Steinbach <alf.p.steinbach+usenet@gmail.com> wrote:
> <code>
> #if !defined( CPP_DECLARE_UNUSED )
> #   define CPP_DECLARE_UNUSED( argName )    \
>         (void)(argName, void(), 0); struct argName; (void)0
> #endif
> // SO user sehe: "(void)0" for semicolon
> // SO user R. Martinho Fernandes, pointed out operator void() problem
> // SO user Johannes Schaub, solution to operator,() problem
> </code>

  That seems worse than just having the compiler warning.

[toc] | [prev] | [next] | [standalone]


#15125

FromQi <no@no.com>
Date2012-04-02 13:48 +0800
Message-ID<jlbekq$693$1@speranza.aioe.org>
In reply to#15121
On 2012-4-2 1:24, Juha Nieminen wrote:
> Qi<no@no.no>  wrote:
>> int main(int argc, char * argv[])
>> {
>>         (void)argc;
>>         (void)argv;
>
>    This seemed like nonsensical code because it does nothing. Then I realized
> that it's an ugly hack to silence the compiler warning about unused
> variables. That's not how you do it.

Ugly? Maybe.
But it makes a lot of sense to me.

There is time that some parameters are not used. Such as implementing
an interface, and the interface function just has extra parameters for
flexibility.

Though I can write "int main(int, char **)", I won't do it because
I expect others may read my code and feel difficult to understand
the function without the parameter name.

For example,
int findSomeThing(int, int); // what's that? Don't know
int findSomeThing(int beginIndex, int endIndex); // oh, find between
// beginIndex, endIndex, but the function doesn't use them.

Of course we can put the parameter name to declaration and omit
in the definition, but then the reader needs to dig into the header
only for parameters when he is reading the source code.

int main(int /*argc*/, char** /*argv*/) ?
To me, it's more ugly and easier to misread than (void)argc.
**? */? How may * and / there in one line?

And I think "(void)argc" is well known for C++ developers, maybe
I'm wrong?



-- 
WQ

[toc] | [prev] | [next] | [standalone]


#15126

FromIan Collins <ian-news@hotmail.com>
Date2012-04-02 17:53 +1200
Message-ID<9tst77FfaaU3@mid.individual.net>
In reply to#15125
On 04/ 2/12 05:48 PM, Qi wrote:
> On 2012-4-2 1:24, Juha Nieminen wrote:
>> Qi<no@no.no>   wrote:
>>> int main(int argc, char * argv[])
>>> {
>>>          (void)argc;
>>>          (void)argv;
>>
>>     This seemed like nonsensical code because it does nothing. Then I realized
>> that it's an ugly hack to silence the compiler warning about unused
>> variables. That's not how you do it.
>
> Ugly? Maybe.
> But it makes a lot of sense to me.
>
> There is time that some parameters are not used. Such as implementing
> an interface, and the interface function just has extra parameters for
> flexibility.
>
> Though I can write "int main(int, char **)", I won't do it because
> I expect others may read my code and feel difficult to understand
> the function without the parameter name.

Then why don't you just write "int main()"?

> For example,
> int findSomeThing(int, int); // what's that? Don't know
> int findSomeThing(int beginIndex, int endIndex); // oh, find between
> // beginIndex, endIndex, but the function doesn't use them.
>
> Of course we can put the parameter name to declaration and omit
> in the definition, but then the reader needs to dig into the header
> only for parameters when he is reading the source code.

If the parameter isn't used (and named), why would the reader look for it?

> int main(int /*argc*/, char** /*argv*/) ?
> To me, it's more ugly and easier to misread than (void)argc.
> **? */? How may * and / there in one line?
>
> And I think "(void)argc" is well known for C++ developers, maybe
> I'm wrong?

Maybe, most people I know simply omit the name.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#15127

FromQi <no@no.com>
Date2012-04-02 13:57 +0800
Message-ID<jlbf5d$8ae$1@speranza.aioe.org>
In reply to#15126
On 2012-4-2 13:53, Ian Collins wrote:
>
> Then why don't you just write "int main()"?

"main" function is only the one in my sample code.
I have a lot of functions that can't omit the parameters
completely...

> If the parameter isn't used (and named), why would the reader look for it?

Because the parameter name can help readability and help to
understand the function, IMHO.


-- 
WQ

[toc] | [prev] | [next] | [standalone]


#15129

FromIan Collins <ian-news@hotmail.com>
Date2012-04-02 18:12 +1200
Message-ID<9tsu9hFfaaU4@mid.individual.net>
In reply to#15127
On 04/ 2/12 05:57 PM, Qi wrote:
> On 2012-4-2 13:53, Ian Collins wrote:
>>
>> Then why don't you just write "int main()"?
>
> "main" function is only the one in my sample code.
> I have a lot of functions that can't omit the parameters
> completely...
>
>> If the parameter isn't used (and named), why would the reader look for it?
>
> Because the parameter name can help readability and help to
> understand the function, IMHO.

Surly the argument about how to comment out the name is evidence that 
simply omitting the name is the best documentation for a parameter that 
isn't used?  I've yet to see a case where clutter helps readability.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#15130

FromMiles Bader <miles@gnu.org>
Date2012-04-02 15:32 +0900
Message-ID<87bona8x02.fsf@catnip.gol.com>
In reply to#15129
Ian Collins <ian-news@hotmail.com> writes:
>> Because the parameter name can help readability and help to
>> understand the function, IMHO.
>
> Surly the argument about how to comment out the name is evidence that
> simply omitting the name is the best documentation for a parameter
> that isn't used?  I've yet to see a case where clutter helps
> readability.

I think it depends.

For instance, consider the initial (highest-level) definition of a
virtual method.  You want the parameter names because they're acting
as documentation for the interface (and the method comment probably
refers to them by name).  But I've found that I often use an inline
method body with a trivial "default definition" that doesn't reference
any of the parameters (and just returns false or something).

I don't want to use an out-of-line method definition for that method
(it's just annoying, and the inline definition actually provides good
documentation of such a trivial default), but the compiler complains
because I don't reference any of the arguments[*], although obviously
the arguments may be referenced by overrides.  What I usually do is
just comment out parameter names.

[*] I actually submitted a bug report trying to make an argument that
g++ shouldn't warn about unreferenced arguments in inline definitions
of virtual methods, but didn't get much sympathy....

-miles

-- 
Omochiroi!

[toc] | [prev] | [next] | [standalone]


#15128

FromMiles Bader <miles@gnu.org>
Date2012-04-02 14:58 +0900
Message-ID<87mx6u8ykw.fsf@catnip.gol.com>
In reply to#15125
Qi <no@no.com> writes:
> And I think "(void)argc" is well known for C++ developers, maybe
> I'm wrong?

I've never seen it used before.

OTOH, it's reasonably obvious what it does (to me at least)....

Whether it's more or less ugly than just commenting out the parameter
names, e.g. "int /*argc*/, char **/*argv*/" is a matter of opinion I
suppose...

-Miles

-- 
o The existentialist, not having a pillow, goes everywhere with the book by
  Sullivan, _I am going to spit on your graves_.

[toc] | [prev] | [next] | [standalone]


#15131

FromJuha Nieminen <nospam@thanks.invalid>
Date2012-04-02 10:11 +0000
Message-ID<4f797b49$0$2798$7b1e8fa0@news.nbl.fi>
In reply to#15125
Qi <no@no.com> wrote:
> Though I can write "int main(int, char **)", I won't do it because
> I expect others may read my code and feel difficult to understand
> the function without the parameter name.

  So instead you put no-op lines of code that are even more confusing,
and which exist solely as a hack to get rid of some compiler warnings?

> Of course we can put the parameter name to declaration and omit
> in the definition, but then the reader needs to dig into the header
> only for parameters when he is reading the source code.

  Exactly how does knowing the parameter's name help understanding
the implementation of the function, which does not use said name?

  "Hey, I can't understand this function implementation because one
of the unused parameters is not named. It confuses me. I have no idea
what this implementation, which doesn't use that parameter, is doing."

> And I think "(void)argc" is well known for C++ developers, maybe
> I'm wrong?

  I have been programming with C++ for over 15 years, most of that
time professionally. I have never seen that hack used before.

[toc] | [prev] | [next] | [standalone]


#15132

FromQi <no@no.com>
Date2012-04-02 19:04 +0800
Message-ID<jlc13h$kjj$1@speranza.aioe.org>
In reply to#15131
On 2012-4-2 18:11, Juha Nieminen wrote:
>> And I think "(void)argc" is well known for C++ developers, maybe
>> I'm wrong?
>
>    I have been programming with C++ for over 15 years, most of that
> time professionally. I have never seen that hack used before.

Hmmm. Maybe I was wrong.
If "(void)argc" is not well known, I will definitely not use
it any longer.

Indeed when I first read "(void)argc" before I knew it, I needed
to think a moment about what it does...

Thanks for pointing that out.


-- 
WQ

[toc] | [prev] | [next] | [standalone]


#15134

FromQi <no@no.com>
Date2012-04-02 19:17 +0800
Message-ID<jlc1tj$kjj$3@speranza.aioe.org>
In reply to#15132
Hi all,

Thanks for let me know my that potential mistake.
I started another thread. Please post there for this topic.
It's too off topic in this thread. :-)


-- 
WQ

[toc] | [prev] | [next] | [standalone]


#15139

Fromjgk@panix.com (Joe keane)
Date2012-04-02 14:41 +0000
Message-ID<jlcdqt$ltg$1@reader1.panix.com>
In reply to#15117
In article <jl8d4h$hbf$1@speranza.aioe.org>, Qi  <no@no.no> wrote:
>int main(int argc, char * argv[])
>{
>	(void)argc;
>	(void)argv;
>
>	string s;
>	test(s);
>	
>	return 0;
>}

That is an old C idiom, and there's nothing wrong with it.

Saying 'comment out the parameter' misses the point.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web