int x = 1; // Not Constant
class A {
public:
int value = x;
int value2 { x };
A(int a) : value(x), value2(x) {}
A(int a, int b) : value{ x }, value2{ x } {}
constexpr A() : value{ 0 }, value2{ 0 } {}
};
constexpr int function(A obj1, A obj2, A obj3, A obj4, A obj5, A obj6, A obj7){
return 1;
}
int main(){
int y = 2; // Not Constant
A obj1 (y);
A obj2 { y };
A obj3 = y ;
A obj4 = { y };
A obj5 (y, y);
A obj6 { y, y);
A obj7 = { y, y };
int var = function(obj1, obj2, obj3, obj4, obj5, obj6, obj7);
return 0;
}
C++ 11 Standard (ISO/IEC 14882: 2011), sekcja 3.9, pkt 10 stanów (Kopalnia nacisk):Dosłowne Rodzaj Klasy w C++ 11/C++ 14
Typ jest dosłowny rodzaj jeśli jest to:
- typu skalarnego; lub
- typ odniesienia; lub
- typu klasy (Rozdział 9), który posiada wszystkie z następujących właściwości:
- ma trywialne destructor
- każde połączenie konstruktora pełnej ekspresji w szynie albo-same wymiary initializers dla nie statycznych elementów danych (jeśli występują) jest wyrażeniem stałym (5.19),
- jest to typ agregacyjny (8.5.1) lub ma co najmniej jeden konstruktor constexpr lub szablon konstruktora, który nie jest kopią lub przenieść konstruktora i
- go ma wszystkie niestatyczne elementy danych i klasy bazowe typów literowych; lub
- tablica typu literalnego.
Moim zdaniem, biorąc pod uwagę kulę w pogrubienie, class A
nie jest dosłownym typu w C++ 11, ponieważ nie ma połączenia konstruktor i klamra lub równy-inicjalizatory danych non-statycznej członkowie, którzy nie są wyrażeniami stałymi. Próbowałem wstawić constexpr
przed definicją konstruktora, a także przypisać wywołanie konstruktora do zmiennej constexpr
, aby sprawdzić, czy rzeczywiście kompilator narzeka, ponieważ nie są to wyrażenia stałe. Jednak zarówno Clang, jak i GCC skompilują go pomyślnie. Więc prawdopodobnie jestem w błędzie.
- Czy ktoś wie, dlaczego
class A
jest literałem?
Pocisk pogrubione usunięto C++ 14 (N3652), więc rozumie class A
jest dosłownym typu C++ 14. Muszę wiedzieć, ponieważ function
jest constexpr
, a zatem each of its parameter types shall be a literal type
(C++ 11/C++ 14 Standard, Rozdział 7.1.15, Ustęp 3).
EDYCJA: W oryginalnym poście użyłem prostego przykładu, aby ułatwić czytanie i wyjaśniłem, że próbowałem już wielu kombinacji. Teraz zaktualizowałem ten przykład niektórymi z tych kombinacji, aby pokazać, że próbowałem różnych wywołań konstruktora, definicji i niestatycznych inicjalizacji elementów danych. Dzięki.
"Czy ktoś wie, dlaczego klasa A jest literalna? *" Nie jest to w C++ 11. I żaden z kodu, który pokazałeś * nie wymaga * żeby był literalnym typem. Więc w czym problem? –
Czy wiesz, czym jest * inicjator klamrowy lub równy *? –
@ T.C. Myślę, że * inicjator typu "brace-lub-equal" to 'int x {y}' lub 'int x = y'. Zwykle mówię * member-initializer-list * dla inicjalizacji w konstruktorze, jak podczas inicjalizacji 'value' w' A (int z): value (x) {} ', ale przeczytałem też wiele osób odnoszących się do tego jak * inicjator typu "brace-lub-equal" *. Proszę mnie poprawić, jeśli popełniłem jakiś błąd. W każdym przypadku próbowałem wielu kombinacji nawiasów klamrowych, równych itd. Zarówno dla samego obiektu, jak i dla zmiennej 'value' w konstruktorze, a wynik jest taki sam. Dzięki. –