const char* jako parametr szablonu klasy

0

Hej,
muszę przekazać za pomocą parametru szablonu klasy zmienną typu const char*:

class JakasKlasa
{
public:
    static constexpr const char* const NAME = "abc";
};

Troszkę powalczyłem z tym i zrobiłem coś takiego:

template<const char* const& name>
class JakasKlasa2
{
public:
    JakasKlasa2() {
        std::cout << name << std:endl;
    }
};

// ...
JakasKlasa2<JakasKlasa::NAME> variableA;

Tylko co ja właściwie zrobiłem? Co to jest const char* const& ? Czy to jest w ogóle prawidłowe podejście?
Spr. GCC 8.x, Clang i MSVC - wszędzie się kompiluje.
Jedynie Visual Studio 2017 podkreśla błąd.

Chcę się upewnić, że to potem nie przestanie w magiczny sposób działać.
Nie mam możliwości zmiany typu zmiennej JakasKlasa::NAME i musi ona być przekazana jako parametr szablonu klasy niestety.

2

To co robisz jest niby poprawne, ale jest raczej złą praktyką. Specjalizujesz po wartości wskaźnika do zmiennej globalnej.

0

Musisz odpowiedzieć sobie na pytanie, do czego ci to jest potrzebne?

Jeżeli nie potrzebujesz tego do celów nauczania, nie masz zrobić tego na ćwiczenia, to zmień to na coś innego.

W zasadzie najprostsza możliwość to zadeklarowanie zmiennej globalnej, tak jak w przykładzie poniżej: Ważne jest to, że zmienna name jest utworzona w zakresie static storage a jej adres jest stałym wyrażeniem.

#include <iostream>

using namespace std;

constexpr char name[] = "name";

template< const char* name >
struct Foo
{
    Foo() { cout << name << endl; }
};

int main()
{
   Foo<name> foo;
   return 0;
}

Inną możliwością obejścia problemu jest użycie makr (należy to traktować jako ciekawostkę, gdyż z wielu względów nie powinno się ich stosować w praktyce, a przynajmniej nie w tym przypadku) .

#include <iostream>

using namespace std;

#define MACRO_GET_1(str, i) \
    (sizeof(str) > (i) ? str[(i)] : 0)

#define MACRO_GET_4(str, i) \
    MACRO_GET_1(str, i+0),  \
    MACRO_GET_1(str, i+1),  \
    MACRO_GET_1(str, i+2),  \
    MACRO_GET_1(str, i+3)

#define MACRO_GET_16(str, i) \
    MACRO_GET_4(str, i+0),   \
    MACRO_GET_4(str, i+4),   \
    MACRO_GET_4(str, i+8),   \
    MACRO_GET_4(str, i+12)

#define MACRO_GET_64(str, i) \
    MACRO_GET_16(str, i+0),  \
    MACRO_GET_16(str, i+16), \
    MACRO_GET_16(str, i+32), \
    MACRO_GET_16(str, i+48)

#define STRING(str) MACRO_GET_64(str, 0), 0

template< char ...code >
struct FooI
{
    FooI(){ ( ( cout << code ) , ... ) ; cout << endl ; }
};

int main()
{
   FooI<STRING("ABC")> fooI1;
   FooI<STRING("CDE")> fooI2;
   FooI<STRING("EFG")> fooI3;
}

wandbox

1

Dla mnie pytanie cierpi na problem XY.
Opisz problem jaki ma rozwiązać ten kod, a nie problem jaki masz z tym kodem.

1

Czytając między wierszami:

template<typename Conf>
class JakasKlasa2
{
public:
    JakasKlasa2() {
        std::cout << Conf::name() << std::endl;
    }
};

class KonifgracjaPole {
public:
    [[nodiscard]] static constexpr std::string_view name() noexcept {
        return "Kartofle";
    }
};

class KonifgracjaSad {
public:
    [[nodiscard]] static constexpr std::string_view name() noexcept {
        return "Gruszki";
    }
};
...
JakasKlasa2<KonifgracjaSad> x;

https://wandbox.org/permlink/NTQlVo49KiDwyEQx

Zaleta jest taka, że konfiguracja może trzymać więcej różnych danych, a twoje pozwala podać jedną wartość na parametr szablonu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1