Co to jest const void?

89

Opis std::is_voidstwierdza, że:

Zapewnia stałą składową, która jest równa true, jeśli T jest typem void, const void, volatile void lub const volatile void.

Więc co mogłoby być const void, lub volatile void?

Ta odpowiedź stwierdza, że const voidzwracany typ byłby nieprawidłowy (jednak kompiluje się na VC ++ 2015)

const void foo() { }

Jeśli standardowo const voidjest nieprawidłowy (VC jest błędny) - to co jest const void?

Ajay
źródło
15
Odpowiedź, do której odsyłasz, nie stwierdza, że ​​byłaby nieważna, stwierdza, że ​​byłaby „bez znaczenia”, co moim zdaniem oznacza, że ​​„nie oferuje żadnych korzyści voidbez niej const”.
@hvd, odpowiedź mówi, że kompilator powinien ostrzec / błąd o takiej kwalifikacji. Zakładam, że standard C ++ nie pozwala na kwalifikacje zvoid
Ajay
2
Odpowiedź stwierdza, że ​​kompilator powinien ostrzec o takiej kwalifikacji, nie wspomina o błędzie, a błąd byłby błędny. Ta uwaga dotyczy tylko jakości wdrożenia, a nie zgodności, ale mogę zrozumieć, że nie jest to wcale jasne z samej uwagi.
@Ajay standard nie określa, że ​​powinno być ostrzeżenie, gdy używasz bezsensownego kodu. To była decyzja gcc, aby dać ci dodatkową wskazówkę, że ten kod nic nie robi. Ale VC nie jest w żaden sposób zła.
user1942027
3
@Ajay W odpowiedzi stwierdza się, że clang daje ostrzeżenie, a zdaniem autora inne kompilatory powinny. Gdyby norma na to nie pozwalała, byłby to błąd, a nie ostrzeżenie.
molbdnilo

Odpowiedzi:

94

const voidjest typem, do którego można utworzyć wskaźnik. Jest podobny do zwykłego wskaźnika void, ale konwersje działają inaczej. Na przykład const int*nie można niejawnie przekonwertować na plik void*, ale można go niejawnie przekonwertować na plik const void*. Podobnie, jeśli masz a const void*, nie możesz static_casttego zrobić int*, ale możesz static_castto zrobić const int*.

const int i = 10;
void* vp = &i;                           // error
const void* cvp = &i;                    // ok
auto ip = static_cast<int*>(cvp);        // error
auto cip = static_cast<const int*>(cvp); // ok
Benjamin Lindley
źródło
4
Podczas gdy twoja odpowiedź jest dobra, nie podaje powodu const void, ale jej wszystkie wokół wskaźników pustki i nie-pustki [z (nie) stałością].
Ajay
26
@Ajay: Nie zgadzam się. A const void*to jedyny powód, jaki kiedykolwiek zobaczysz const void. Może być przekazywany jako argument szablonu, ale instancja tego typu argumentu będzie zawsze tworzona tylko z literą *na końcu.
Benjamin Lindley
@BenjaminLindley Można również zobaczyć const voidw pytanie zadawane przez prawnika językowej
cpplearner
3
@Ajay: W pewnym momencie to pytanie staje się pytaniem filozoficznym. „Powodem” const voidjest to, że można tworzyć wszystkie typy w C ++ const. „Istnieje” w taki sam sposób, w jaki voidistnieje. Odpowiedź @Benjamina Lindleya wyjaśnia, co to jest, kiedy ją widzisz i jak jej używasz.
Chris Beck
23

Jako void, const voidjest nieważna typu. Jeśli jednak const voidjest typem zwracanym , to constjest bez znaczenia (aczkolwiek legalne!), Ponieważ [wyrażenie] / 6 :

Jeśli wartość pr ma początkowo typ „ cv T ”, gdzie Tjest niekwalifikowanym typem cv nieklasowym , nie tablicowym, typ wyrażenia jest dostosowywany Tprzed dalszą analizą.

Jednak sam jest prawidłowym typem i występuje np. W funkcjach bibliotecznych w standardzie C , gdzie jest używany do zapewnienia stałej poprawności wskaźników argumentów: int const*nie można konwertować na void*, ale void const*.

Columbo
źródło
const voidponieważ typ zwracany wpływa na typ funkcji, więc nie jest całkowicie bez znaczenia.
cpplearner
1
@cpplearner Z wyjątkiem tego, że jest to pod każdym względem praktycznym, ponieważ nie ma to wpływu ani na podpis funkcji, ani na typ wywołania do niej.
Columbo,
Cóż, może zmienić podpis szablonu funkcji. Jednak +1
cpplearner
@cpplearner W porządku - jednak nadal jest to strata naciśnięć klawiszy.
Columbo,
Zwykle widzimy: const int * nie może przejść do void *, ale const void *.
mgouin
18

Typy mogą wynikać z szablonów; szablon może zawierać const Ti być utworzony z Tas void.

Połączona odpowiedź jest myląca, a raczej ograniczona, ponieważ dotyczy specjalnego przypadku typu innego niż szablon, a nawet wtedy const voidmoże być bez znaczenia , ale jest to prawidłowy kod .

DevSolar
źródło