• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Paczka parametrów, a statyczna stałowyrażeniowa tablica

Object Storage Arubacloud
+1 głos
196 wizyt
pytanie zadane 29 września 2019 w C i C++ przez vector Dyskutant (9,200 p.)

Potrzebowałem manupulować ciągiem znaków w czasie kompilacji więc napisałem sobie oto taki wrapper:

template <char ...Cs>
struct char_seq {
  static constexpr const char
    value[sizeof...(Cs) + 1] =
      {Cs..., '\0'};
};

#include <iostream>
int main() {
  std::cout
    << char_seq<'0', '1'>::value
    << std::endl;
  return 0;
}

Ku mojemu zaskoczeniu powyższy kod nie kompiluje się w standardzie c++11/14, linker wyrzuca taki oto błąd:

// GCC 9.1
/usr/bin/ld: /tmp/ccZZZsJC.o: in function `main':
1.cpp:(.text+0x7): undefined reference to `char_seq<(char)48, (char)49>::value'
collect2: error: ld returned 1 exit status

// Clang 8.0.1
/usr/bin/ld: /tmp/1-bfa92b.o: in function `main':
1.cpp:(.text+0x12): undefined reference to `char_seq<(char)48, (char)49>::value'
clang-8: error: linker command failed with exit code 1 (use -v to see invocation)

Co ciekawe zarówno kompilując za pomocą clanga jak i w gcc z standardem c++17 wszystko ładnie działa. Prawdopodobnie jest jakiś zapisek w standardzie c++11/14 który uniemożliwia zlinkowanie się tego kodu (albo jest to bug kompilatorów lub linkera, ale w to nie wierze bo działą poprawnie w nowszym standardzie).

Czy ktoś z was może wie dlaczego powyższy kod nie kompiluje się w standardzie c++11/14?

 

1 odpowiedź

+1 głos
odpowiedź 29 września 2019 przez RafalS VIP (122,820 p.)
wybrane 1 października 2019 przez vector
 
Najlepsza
template <char ...Cs>

https://en.cppreference.com/w/cpp/language/parameter_pack

template < parameter-list > typename(C++17)|class ... Args(optional) (3)  

EDIT: Na ciekawy błąd trafiłeś. Chodzi o inicjalizację statycznych składowych. Brakuje Ci:

template<char...Cs>
constexpr const char char_seq<Cs...>::value[];

https://en.cppreference.com/w/cpp/language/static

If a const non-inline (since C++17) static data member or a constexpr static data member (since C++11) is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. This definition is deprecated for constexpr data members (since C++17). 

 Informally, an object is odr-used if ... its address is taken

 W C++17 działa, bo

If a static data member is declared constexpr, it is implicitly inline and does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated.

(since C++17)

Właśnie za takie smaczki nie lubie C++. Jest za bardzo niejawny. 

komentarz 29 września 2019 przez vector Dyskutant (9,200 p.)

Jeżeli dobrze rozumiem to ten zapis tylko mówi że można używać słowa kluczowego typename zamiast class w pewnych przypadach deklarowania/definiowania paczek parametrów, nie widzę aby to było związane z moim problemem

// pre c++17
template <template </*...*/> class ...>    // ok
template <template </*...*/> typename ...> // błąd

// post c++17
template <template </*...*/> class ...>    // ok
template <template </*...*/> typename ...> // ok

 

template <char ...Cs>

łapie się pod

type ... Args(optional) (1)  

1) A non-type template parameter pack with an optional name

Ponadto nie wydaje mi się aby to mogło mieć jakikolwiek wpływ ponieważ kompilator nie zgłasza błędu syntaktycznego tylko linker ma problem z zlinkowaniem pliku obiektowego.

No chyba że czegoś nie rozumiem, w takim przypadku proszę o dodatkowe wyjaśnienie.

komentarz 30 września 2019 przez RafalS VIP (122,820 p.)
Racja nie przeanalizowałem tego wystarczająco. Jak coś wymyślę to poprawie odpowiedz
komentarz 30 września 2019 przez RafalS VIP (122,820 p.)
Rozwiązałem problem i edytowałem odpowiedz. Rzuć okiem.
komentarz 1 października 2019 przez vector Dyskutant (9,200 p.)
Po redeklaracji na zewnątrz struktury wszystko działa z c++11/14. Nigdy nie spotkałem się z okresleniem ODR-used, kolejna rzecz do zapamiętania. Dziekuję za pomoc :)

Podobne pytania

0 głosów
2 odpowiedzi 528 wizyt
pytanie zadane 4 października 2018 w C i C++ przez uther1455 Nowicjusz (140 p.)
0 głosów
1 odpowiedź 201 wizyt
pytanie zadane 15 września 2018 w C# przez mati2210 Obywatel (1,110 p.)
+1 głos
1 odpowiedź 145 wizyt
pytanie zadane 5 stycznia 2021 w Offtop przez poldeeek Mądrala (5,980 p.)

92,620 zapytań

141,474 odpowiedzi

319,815 komentarzy

62,005 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...