Re: Bug in c++11 mode when instantiating template with local class

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 6/23/2017 10:46 AM, Jonathan Wakely wrote:
On 22 June 2017 at 17:42, Edward Diener <eldlistmailingz@xxxxxxxxxxxxxx> wrote:
The code below asserts when being compiled with gcc in c++11 mode:

----------------------------------------------------------------------

#include <cassert>

typedef char yes_type;
struct no_type
{
    char padding[8];
};

template
     <
     class enclosing_type,
     class static_type
     >
struct has_static_member_function_StaticFunction
     {
     template<static_type *> struct helper;
     template<class internal_enclosing_type> static yes_type
chkt(helper<&internal_enclosing_type::StaticFunction> *);
     template<class internal_enclosing_type> static no_type chkt(...);
     static const bool
value=(sizeof(chkt<enclosing_type>(0))==sizeof(yes_type));
     };


     class AClass
     {
     public:
         static void StaticFunction()
         {
         }
     };

int main()
{
     class ANestedClass
     {
     public:
         static void StaticFunction()
         {
         }
     };

     assert((has_static_member_function_StaticFunction<ANestedClass,void
()>::value));

     return 0;
}

-------------------------------------------------------------------------

If the 'assert" line instead is:

assert((has_static_member_function_StaticFunction<AClass,void ()>::value));

the assert does not occur. In other words the class template's 'value' is
false when passing the local class and true when passing the non-local
class.

The code is a simplified version of my Boost tti's library code for checking
if a static member function of a given name exists within a class.

Is this a gcc bug or is my code wrong for local classes in c++11 mode, as
opposed to non-local classes ?

I am fully aware that instantiating a template with a local class type is
forbidden prior to c++11.

The compile and link lines, for gcc 7.1 as an example, are:

somepath/g++ -ftemplate-depth-128 -Wno-unused-local-typedefs
-ftrack-macro-expansion=0 -Wno-unused-variable -std=c++11 -O0 -fno-inline
-Wall -pedantic -g -march=i686 -m32 -c -o somepath/example.o example.cpp

somepath/g++ -o example.exe -Wl,--start-group somepath/example.o
-Wl,-Bstatic  -Wl,-Bdynamic  -Wl,--end-group -g -march=i686 -m32

If this is a bug in gcc I will be happy to report it on the bug tracker if
it has not already been reported.





I don't think it's a bug. The code can be simplified considerably:

template<void(*)()> struct helper { };

struct AClass
{
   static void StaticFunction() { }
};

int main()
{
   struct ANestedClass
   {
     static void StaticFunction() { }
   };

   helper<&AClass::StaticFunction> ok;
   helper<&ANestedClass::StaticFunction> error;
}

GCC, Clang and EDG all reject this for the same reason: you're using
the address of a function with no linkage for a non-type template
argument.

[basic.link] says that although ANestedClass has internal linkage, the
static member function has no linkage.

Could you point out where in [basic.link] this is specified ? I admit I have a great deal of trouble understanding the rules for internal, external, and no linkage of names in section 3.5 of the C++ standard. But I do find it odd that if a local class name has internal linkage, a static member function name of that local class has no linkage.


N.B. https://wg21.link/n2187 allowed types with internal linkage to be
used for template arguments, and https://wg21.link/cwg1155 allowed the
addresses of objects with internal linkage to be used for non-type
template arguments, but internal linkage is not the same as no
linkage.

I believe the reason the code is invalid is because otherwise you
could declare an object with external linkage using a type with no
linkage:

static helper<&ANestedClass::StaticFunction> foo;

In your example doesn't 'foo' have internal linkage because it is declared 'static' ?




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux