Bug in c++11 mode when instantiating template with local class
Edward Diener
eldlistmailingz@tropicsoft.com
Fri Jun 23 17:43:00 GMT 2017
On 6/23/2017 10:46 AM, Jonathan Wakely wrote:
> On 22 June 2017 at 17:42, Edward Diener <eldlistmailingz@tropicsoft.com> 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' ?
More information about the Gcc-help
mailing list