Trait sprawdzający dostępność konstruktorów domyślnych

Trait sprawdzający dostępność konstruktorów domyślnych
Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Witam!

Czytam ostatnio artykuł o generycznym singletonie i trafiłem tam na fragment kodu, który niestety nie bardzo rozumiem. Prosiłbym o wytłumaczenie jego dokładnego działania. Tutaj kod:

Kopiuj
namespace std
{
 
  template <typename T>
  struct is_default_or_protected_constructible
  {
    struct X : T {};
    static const auto value = std::is_default_constructible<X>::value;
  };
 
}

Chodzi szczególnie o fragment:

Kopiuj
struct X : T {} 

Podany kod ma rozstrzygać czy dany typ umożliwia zainicjowanie instancji klasy przez konstruktor domyślny. is_default_constructible<X> mówi nam tylko o konstruktorach znajdujących się w sekcji public klasy. Dlaczego zatem po odziedziczeniu z takiej klasy (w tym wypadku T) nagle możemy dowiedzieć się czegoś dodatkowego o jej konstruktorach, które do tej pory były protected?

kq
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Szczecin
1

Bo klasa X ma dostęp do składowych protected T, w tym konstruktorów.

Tak swoją drogą, teraz tego traita zapisałbym tak:

Kopiuj
namespace detail
{

template<typename T, bool is_final = std::is_final<T>::value>
struct is_default_or_protected_constructible_helper
{
	struct X : T {};
	static constexpr bool value = std::is_default_constructible<X>::value;
};

template<typename T>
struct is_default_or_protected_constructible_helper<T, true>:
		std::is_default_constructible<T>
{
};

}

template<typename T>
struct is_default_or_protected_constructible:
		std::integral_constant<bool, detail::is_default_or_protected_constructible_helper<T>::value>
{
};

template<typename T>
constexpr bool is_default_or_protected_constructible_v = is_default_or_protected_constructible<T>::value;
Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Czy std::is_default_constructible nie wymaga tego by konstruktory były w sekcji public?
Cytując artykuł:

Trait ten wymaga żeby konstruktory badanej klasy były dostępne publicznie.
Jeżeli tak nie jest to cały kod wydaje się dla mnie przerostem formy nad treścią bo wystarczyłoby po prostu sprawdzić typ T a nie bawić się w takie dziedziczenie.

kq
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Szczecin
2

Wymaga, ale to może być konstruktor wygenerowany przez kompilator, niewidzialny w kodzie. Może na przykładzie:

Kopiuj
class Foo
{
protected:
	Foo(){}
};

is_default_constructible<Foo>false
IFF nie jesteś w stanie napisać w kodzie

Kopiuj
Foo f; // error
work_on_foo(f);

Teraz weźmy się za dziedziczenie:

Kopiuj
class Bar : public Foo
{
public:
	Bar(){}
};

Tę klasę możesz bezproblemowo tworzyć:

Kopiuj
Bar b; // OK
work_on_foo(b);
work_on_bar(b);

IFF
is_default_constructible<Bar>true

Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Czyli niezależnie od tego gdzie będzie konstruktor domyślny w klasie dziedziczonej (oprócz private), klasa dziedzicząca wywoła go podczas tworzenia instancji. Zgadza się? I tylko do tego sprowadza się rola tej klasy X?

kq
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Szczecin
1

Tak jest.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.