public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/34073]  New: overloaded template function resolves differently if one type is included in a namespace
@ 2007-11-12 15:21 adl at gnu dot org
  2007-11-12 19:02 ` [Bug c++/34073] " pinskia at gcc dot gnu dot org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: adl at gnu dot org @ 2007-11-12 15:21 UTC (permalink / raw)
  To: gcc-bugs

Two files are appended at the end of this report: temp1.cc and temp2.cc.

temp1.cc is the only file that causes a problem with recent releases
of GCC.  It contains :

1. a template definition of  Structure<S>
2. a template definition of  op_is_finite<S>(const Structure<S>*)
3. a template definition of  algebra::AlphabetSet<L> inheriting from Structure
4. a template definition of  Element<L> 
   that calls op_is_finite(const algebra::AlphabetSet<L>*) in its ctor
5. a template overloaded definition for 
                             op_is_finite<L>(const algebra::AlphabetSet<L>*)
6. a main function that instantiate Element<char>.

Because all definitions but main() are template, I expect the call to
op_is_finite() in the ctor of Element<L> (#4) to be resolved during the 
instantiation of Element<char> (#6) after the second definition
of op_is_finite() (#5) has been read.  So the call would be bound
to that second definition and not to the first.

I have tested three GCC versions :
g++-3.4 (GCC) 3.4.6 (Debian 3.4.6-6)
g++-4.1 (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
g++-4.2 (GCC) 4.2.3 20071014 (prerelease) (Debian 4.2.2-3)

Both 4.1 and 4.2 behave identically: they seem to ignore the second
definition of op_is_finite and try to call the first.

3.4 does what we expect: it calls the second definition.


We have found at least two ways to alter temp1.cc such that 4.2 will
compile it.

- One is to move the second definition of op_is_finite() (#5) before its
  use in the constructor of Element<L> (#4).  

  This ordering would make sense to me if the functions were not
  template, but it's not clear why this would change anything in
  the resolution of template overloaded functions.  I might be
  missing something.

- Another possibility is to move AlphabetSet<L> struct out of 
  the "algebra::" namespace.  temp2.cc contains the updated
  code.  

  I'm really surprized that 4.2 compiles temp2.cc
  without problem and fails on temp1.cc.




//////////////////////////////////////////////////////
//////////////// temp1.cc starts here ////////////////
//////////////////////////////////////////////////////

template<typename S> struct Structure {};

template<typename S>
bool op_is_finite (const Structure<S>*)
{
  // Error on purpose, this function is not expected to be instantiated.
  return Structure<S>();
}

namespace algebra
{
  template <typename L>
  struct AlphabetSet : public Structure<AlphabetSet<L> > {};
}

template <typename L>
struct Element
{
  Element()
  {
    op_is_finite(static_cast<const algebra::AlphabetSet<L>*>(0));
  }
};

template <typename L>
bool op_is_finite(const algebra::AlphabetSet<L>*)
{
  // This is the function we want to be called.
  return true;
}

int main()
{
  Element<char> alpha;
}

// % g++-3.4 -Wall -W temp1.cc
// % g++-4.2 -Wall -W temp1.cc
// temp1.cc: In function 'bool op_is_finite(const Structure<S>*) [with S =
algebra::AlphabetSet<char>]':
// temp1.cc:21:   instantiated from 'Element<L>::Element() [with L = char]'
// temp1.cc:34:   instantiated from here
// temp1.cc:7: error: cannot convert 'Structure<algebra::AlphabetSet<char> >'
to 'bool' in return

//////////////////////////////////////////////////////
//////////////// temp2.cc starts here ////////////////
//////////////////////////////////////////////////////

template<typename S> struct Structure {};

template<typename S>
bool op_is_finite (const Structure<S>*)
{
  // Error on purpose, this function is not expected to be instantiated.
  return Structure<S>();
}

template <typename L>
struct AlphabetSet : public Structure<AlphabetSet<L> > {};

template <typename L>
struct Element
{
  Element()
  {
    op_is_finite(static_cast<const AlphabetSet<L>*>(0));
  }
};

template <typename L>
bool op_is_finite(const AlphabetSet<L>*)
{
  // This is the function that is called, as we expected.
  return true;
}

int main()
{
  Element<char> alpha;
}

// % g++-3.4 -Wall -W temp2.cc
// % g++-4.2 -Wall -W temp2.cc


-- 
           Summary: overloaded template function resolves differently if one
                    type is included in a namespace
           Product: gcc
           Version: 4.2.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: adl at gnu dot org
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug c++/34073] overloaded template function resolves differently if one type is included in a namespace
  2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
@ 2007-11-12 19:02 ` pinskia at gcc dot gnu dot org
  2007-11-12 21:17 ` steven at gcc dot gnu dot org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2007-11-12 19:02 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #1 from pinskia at gcc dot gnu dot org  2007-11-12 19:02 -------
And this is expected behavior of C++ Lookup in templates.


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug c++/34073] overloaded template function resolves differently if one type is included in a namespace
  2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
  2007-11-12 19:02 ` [Bug c++/34073] " pinskia at gcc dot gnu dot org
@ 2007-11-12 21:17 ` steven at gcc dot gnu dot org
  2007-11-12 21:29 ` pinskia at gcc dot gnu dot org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: steven at gcc dot gnu dot org @ 2007-11-12 21:17 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #2 from steven at gcc dot gnu dot org  2007-11-12 21:17 -------
Perhaps you can give a little more verbose explanation why this is invalid?


-- 

steven at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |pinskia at gcc dot gnu dot
                   |                            |org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug c++/34073] overloaded template function resolves differently if one type is included in a namespace
  2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
  2007-11-12 19:02 ` [Bug c++/34073] " pinskia at gcc dot gnu dot org
  2007-11-12 21:17 ` steven at gcc dot gnu dot org
@ 2007-11-12 21:29 ` pinskia at gcc dot gnu dot org
  2007-11-12 22:08 ` adl at gnu dot org
  2007-11-20 11:30 ` [Bug c++/34073] New: " mahmoodn
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2007-11-12 21:29 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #3 from pinskia at gcc dot gnu dot org  2007-11-12 21:29 -------
Basically the namelookup for op_is_finite in Element will lookup the previous
declared ones (at definition time) and then will do argument dependent lookup
(at instaintation time).  Argument dependent lookup only looks at definition in
the namespace containing that argument type.  So in the second case the
argument type (AlphabetSet) is in the global namespace so it will see the
function, while in the first case it is located in algebra namespace and there
is no matching function in that namespace.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug c++/34073] overloaded template function resolves differently if one type is included in a namespace
  2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
                   ` (2 preceding siblings ...)
  2007-11-12 21:29 ` pinskia at gcc dot gnu dot org
@ 2007-11-12 22:08 ` adl at gnu dot org
  2007-11-20 11:30 ` [Bug c++/34073] New: " mahmoodn
  4 siblings, 0 replies; 6+ messages in thread
From: adl at gnu dot org @ 2007-11-12 22:08 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #4 from adl at gnu dot org  2007-11-12 22:08 -------
Thank you for the very clear explanation, Andrew.

Indeed, adding a "namespace algebra" around the second definition of
op_is_finite() will solve my problem.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Bug c++/34073]  New: overloaded template function resolves  differently if one type is included in a namespace
  2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
                   ` (3 preceding siblings ...)
  2007-11-12 22:08 ` adl at gnu dot org
@ 2007-11-20 11:30 ` mahmoodn
  4 siblings, 0 replies; 6+ messages in thread
From: mahmoodn @ 2007-11-20 11:30 UTC (permalink / raw)
  To: gcc-bugs


Where are "temp1.cc" and "temp2.cc" so that I correct them? are they part of
the compiler?

Thanks,


pinskia at gcc dot gnu dot org wrote:
> 
> Two files are appended at the end of this report: temp1.cc and temp2.cc.
> 
> temp1.cc is the only file that causes a problem with recent releases
> of GCC.  It contains :
> 
> 1. a template definition of  Structure<S>
> 2. a template definition of  op_is_finite<S>(const Structure<S>*)
> 3. a template definition of  algebra::AlphabetSet<L> inheriting from
> Structure
> 4. a template definition of  Element<L> 
>    that calls op_is_finite(const algebra::AlphabetSet<L>*) in its ctor
> 5. a template overloaded definition for 
>                              op_is_finite<L>(const
> algebra::AlphabetSet<L>*)
> 6. a main function that instantiate Element<char>.
> 
> Because all definitions but main() are template, I expect the call to
> op_is_finite() in the ctor of Element<L> (#4) to be resolved during the 
> instantiation of Element<char> (#6) after the second definition
> of op_is_finite() (#5) has been read.  So the call would be bound
> to that second definition and not to the first.
> 
> I have tested three GCC versions :
> g++-3.4 (GCC) 3.4.6 (Debian 3.4.6-6)
> g++-4.1 (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
> g++-4.2 (GCC) 4.2.3 20071014 (prerelease) (Debian 4.2.2-3)
> 
> Both 4.1 and 4.2 behave identically: they seem to ignore the second
> definition of op_is_finite and try to call the first.
> 
> 3.4 does what we expect: it calls the second definition.
> 
> 
> We have found at least two ways to alter temp1.cc such that 4.2 will
> compile it.
> 
> - One is to move the second definition of op_is_finite() (#5) before its
>   use in the constructor of Element<L> (#4).  
> 
>   This ordering would make sense to me if the functions were not
>   template, but it's not clear why this would change anything in
>   the resolution of template overloaded functions.  I might be
>   missing something.
> 
> - Another possibility is to move AlphabetSet<L> struct out of 
>   the "algebra::" namespace.  temp2.cc contains the updated
>   code.  
> 
>   I'm really surprized that 4.2 compiles temp2.cc
>   without problem and fails on temp1.cc.
> 
> 
> 
> 
> //////////////////////////////////////////////////////
> //////////////// temp1.cc starts here ////////////////
> //////////////////////////////////////////////////////
> 
> template<typename S> struct Structure {};
> 
> template<typename S>
> bool op_is_finite (const Structure<S>*)
> {
>   // Error on purpose, this function is not expected to be instantiated.
>   return Structure<S>();
> }
> 
> namespace algebra
> {
>   template <typename L>
>   struct AlphabetSet : public Structure<AlphabetSet<L> > {};
> }
> 
> template <typename L>
> struct Element
> {
>   Element()
>   {
>     op_is_finite(static_cast<const algebra::AlphabetSet<L>*>(0));
>   }
> };
> 
> template <typename L>
> bool op_is_finite(const algebra::AlphabetSet<L>*)
> {
>   // This is the function we want to be called.
>   return true;
> }
> 
> int main()
> {
>   Element<char> alpha;
> }
> 
> // % g++-3.4 -Wall -W temp1.cc
> // % g++-4.2 -Wall -W temp1.cc
> // temp1.cc: In function 'bool op_is_finite(const Structure<S>*) [with S =
> algebra::AlphabetSet<char>]':
> // temp1.cc:21:   instantiated from 'Element<L>::Element() [with L =
> char]'
> // temp1.cc:34:   instantiated from here
> // temp1.cc:7: error: cannot convert 'Structure<algebra::AlphabetSet<char>
> >'
> to 'bool' in return
> 
> //////////////////////////////////////////////////////
> //////////////// temp2.cc starts here ////////////////
> //////////////////////////////////////////////////////
> 
> template<typename S> struct Structure {};
> 
> template<typename S>
> bool op_is_finite (const Structure<S>*)
> {
>   // Error on purpose, this function is not expected to be instantiated.
>   return Structure<S>();
> }
> 
> template <typename L>
> struct AlphabetSet : public Structure<AlphabetSet<L> > {};
> 
> template <typename L>
> struct Element
> {
>   Element()
>   {
>     op_is_finite(static_cast<const AlphabetSet<L>*>(0));
>   }
> };
> 
> template <typename L>
> bool op_is_finite(const AlphabetSet<L>*)
> {
>   // This is the function that is called, as we expected.
>   return true;
> }
> 
> int main()
> {
>   Element<char> alpha;
> }
> 
> // % g++-3.4 -Wall -W temp2.cc
> // % g++-4.2 -Wall -W temp2.cc
> 
> 
> -- 
>            Summary: overloaded template function resolves differently if
> one
>                     type is included in a namespace
>            Product: gcc
>            Version: 4.2.3
>             Status: UNCONFIRMED
>           Severity: normal
>           Priority: P3
>          Component: c++
>         AssignedTo: unassigned at gcc dot gnu dot org
>         ReportedBy: adl at gnu dot org
>  GCC build triplet: i686-pc-linux-gnu
>   GCC host triplet: i686-pc-linux-gnu
> GCC target triplet: i686-pc-linux-gnu
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34073
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/-Bug-c%2B%2B-34073---New%3A-overloaded-template-function-resolves-differently-if-one-type-is-included-in-a-namespace-tf4791742.html#a13855273
Sent from the gcc - bugs mailing list archive at Nabble.com.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-11-20 11:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-12 15:21 [Bug c++/34073] New: overloaded template function resolves differently if one type is included in a namespace adl at gnu dot org
2007-11-12 19:02 ` [Bug c++/34073] " pinskia at gcc dot gnu dot org
2007-11-12 21:17 ` steven at gcc dot gnu dot org
2007-11-12 21:29 ` pinskia at gcc dot gnu dot org
2007-11-12 22:08 ` adl at gnu dot org
2007-11-20 11:30 ` [Bug c++/34073] New: " mahmoodn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).