diff --git a/riegeli/base/initializer.h b/riegeli/base/initializer.h index 8eb77f1d..f690dba4 100644 --- a/riegeli/base/initializer.h +++ b/riegeli/base/initializer.h @@ -26,6 +26,9 @@ namespace riegeli { +template +class Initializer; + namespace initializer_internal { // `IsConstructible::value` is `true` if `T` is implicitly @@ -43,6 +46,16 @@ struct IsConstructible : std::is_convertible {}; template struct IsConstructible : std::is_constructible {}; +// `IsInitializer` detects `Initializer` type with the given type parameter and +// any `allow_explicit`. + +template +struct IsInitializer : std::false_type {}; + +template +struct IsInitializer> : std::true_type { +}; + // Part of `Initializer` common to all specializations. template class InitializerBase { @@ -81,10 +94,7 @@ class InitializerBase { explicit InitializerBase(const Methods* methods); - template < - typename Arg, - std::enable_if_t, InitializerBase>::value, - int> = 0> + template explicit InitializerBase(const Methods* methods, Arg&& arg); template @@ -248,10 +258,7 @@ class InitializerValueBase : public InitializerBase { explicit InitializerValueBase(const Methods* methods) : InitializerValueBase::InitializerBase(methods) {} - template , InitializerValueBase>::value, - int> = 0> + template explicit InitializerValueBase(const Methods* methods, Arg&& arg) : InitializerValueBase::InitializerBase(methods, std::forward(arg)) { } @@ -381,11 +388,7 @@ class InitializerAssignableValueBase : public InitializerValueBase { explicit InitializerAssignableValueBase(const Methods* methods) : InitializerAssignableValueBase::InitializerValueBase(methods) {} - template < - typename Arg, - std::enable_if_t, - InitializerAssignableValueBase>::value, - int> = 0> + template explicit InitializerAssignableValueBase(const Methods* methods, Arg&& arg) : InitializerAssignableValueBase::InitializerValueBase( methods, std::forward(arg)) {} @@ -457,11 +460,12 @@ class Initializer // Constructs `Initializer` from a value convertible to `T`. template < typename Arg, - std::enable_if_t, Initializer>>, - initializer_internal::IsConstructible< - allow_explicit, T, Arg&&>>::value, - int> = 0> + std::enable_if_t< + absl::conjunction>>, + initializer_internal::IsConstructible< + allow_explicit, T, Arg&&>>::value, + int> = 0> /*implicit*/ Initializer(Arg&& arg ABSL_ATTRIBUTE_LIFETIME_BOUND) : Initializer::InitializerAssignableValueBase( &Initializer::InitializerAssignableValueBase:: @@ -515,6 +519,12 @@ class Initializer template kMethodsFromConstMaker, args.maker()) {} + // Constructs `Initializer` from `Initializer` with a different + // `allow_explicit` by adopting its state instead of wrapping. + template + /*implicit*/ Initializer(Initializer initializer) + : Initializer::InitializerAssignableValueBase(std::move(initializer)) {} + // Deprecated: use `riegeli::Maker(args...)` instead of // `std::forward_as_tuple(args...)`. // @@ -561,11 +571,12 @@ class Initializer` from a value convertible to `T`. template < typename Arg, - std::enable_if_t, Initializer>>, - initializer_internal::IsConstructible< - allow_explicit, T, Arg&&>>::value, - int> = 0> + std::enable_if_t< + absl::conjunction>>, + initializer_internal::IsConstructible< + allow_explicit, T, Arg&&>>::value, + int> = 0> /*implicit*/ Initializer(Arg&& arg ABSL_ATTRIBUTE_LIFETIME_BOUND) : Initializer::InitializerValueBase( &Initializer::InitializerValueBase::template kMethodsFromObject< @@ -617,6 +628,12 @@ class Initializer, args.maker()) {} + // Constructs `Initializer` from `Initializer` with a different + // `allow_explicit` by adopting its state instead of wrapping. + template + /*implicit*/ Initializer(Initializer initializer) + : Initializer::InitializerValueBase(std::move(initializer)) {} + // Deprecated: use `riegeli::Maker(args...)` instead of // `std::forward_as_tuple(args...)`. // @@ -655,11 +672,12 @@ class Initializer` from a value convertible to `T`. template < typename Arg, - std::enable_if_t, Initializer>>, - initializer_internal::IsConstructible< - allow_explicit, T, Arg&&>>::value, - int> = 0> + std::enable_if_t< + absl::conjunction>>, + initializer_internal::IsConstructible< + allow_explicit, T, Arg&&>>::value, + int> = 0> /*implicit*/ Initializer(Arg&& arg ABSL_ATTRIBUTE_LIFETIME_BOUND) : Initializer::InitializerBase( &Initializer::InitializerBase::template kMethodsFromObject, @@ -708,6 +726,12 @@ class Initializer, args.maker()) {} + // Constructs `Initializer` from `Initializer` with a different + // `allow_explicit` by adopting its state instead of wrapping. + template + /*implicit*/ Initializer(Initializer initializer) + : Initializer::InitializerBase(std::move(initializer)) {} + // Deprecated: use `riegeli::Maker(args...)` instead of // `std::forward_as_tuple(args...)`. // @@ -798,9 +822,7 @@ inline InitializerBase::InitializerBase(const Methods* methods) : methods_(methods) {} template -template , InitializerBase>::value, int>> +template inline InitializerBase::InitializerBase(const Methods* methods, Arg&& arg) : methods_(methods), context_(const_cast*>(&arg)) {}