Why static const char * template template member is not initialized

I have some C ++ 11 code which I am trying to connect to Visual C ++ Compiler 2015. The source code works fine, however I need to rewrite it to solve problems using constexpr.

Source code (simplified example)

#include <iostream>

struct String
{
    static constexpr const char * value{ "STRING" };
};

template<typename Base>
class Derived
{
public:
    static constexpr const char * value{ Base::value };
};

template<typename BarType>
struct Foo
{
    static constexpr const char * value{ BarType::value };
};

using Bar = Derived<String>;
using FooBar = Foo<Bar>;

int main()
{
    std::cout << "FooBar::value = " << FooBar::value << std::endl;
}

Fingerprints:

FooBar::value = STRING

However, when I rewrite, some static variables are not initialized. Despite the fact that it just compiles.

Ported Code (not working)

#include <iostream>

struct String
{
    static const char * value;
};
const char * String::value = "STRING";

template<typename Base>
class Derived
{
public:
    static const char * value;
};
template<typename Base>
const char * Derived<Base>::value = { Base::value };

template<typename BarType>
struct Foo
{
    static const char * value;
};
template<typename BarType>
const char * Foo<BarType>::value = { BarType::value };

using Bar = Derived<String>;
using FooBar = Foo<Bar>;

int main()
{
    std::cout << "FooBar::value = " << FooBar::value << std::endl;
}

Fingerprints:

// nothing (Segmentation fault)
  • Why is this happening?

  • How do I fix / get around it?

This can be reproduced in Clang and Visual-C ++, however GCC FooBar::value = STRINGalso prints in the second example.

Update: Working Solution

@serge-ballesta. , . , constexpr VS.

+4
2

, [basic.start.init]:

,

Derived<Base>::value Foo<BarType>::value , . . , , .. value s .

, . :

Derived<Base>::value ==> 0
Foo<BarType>::value ==> 0
Derived<Base>::value ==> Base::value
Foo<BarType>::value ==> BarType::value

:

Derived<Base>::value ==> 0
Foo<BarType>::value ==> 0
Foo<BarType>::value ==> BarType::value
Derived<Base>::value ==> Base::value

Derived<Base>::value, Foo<BarType>::value "STRING". , , 0. , , .

+2

@ .

. String , String::value () .

:

  • init Foo :

    ...
    template<typename BarType>
    struct Foo
    {
        static const char * value;
            static void init() {
                Foo::value = BarType::value;
            }
    };
    
    template<typename BarType>
    const char * Foo<BarType>::value;
    
    using Bar = Derived<String>;
    using FooBar = Foo<Bar>;
    
    int main()
    {
        FooBar::init();
        std::cout << "FooBar::value = " << FooBar::value << std::endl;
    }
    
  • value Foo:

    ...
    template<typename BarType>
    struct Foo
    {
        static const char * value() {
            return BarType::value;;
        }
    };
    
    using Bar = Derived<String>;
    using FooBar = Foo<Bar>;
    
    int main()
    {
        std::cout << "FooBar::value = " << FooBar::value() << std::endl;
    }
    
+1

Source: https://habr.com/ru/post/1610263/


All Articles