Skip to content

Commit

Permalink
Add InitializerTarget<T>::type and InitializerTargetT<T> which de…
Browse files Browse the repository at this point in the history
…duce the

appropriate target type such that `T` is convertible to
`Initializer<InitializerTargetT<T>>`.

This allows a single template to uniformly handle a `Target` passed directly and
`Initializer<Target>`. This is also useful for CTAD guides to deduce a template
argument as `InitializerTargetT<T>`.

This is undefined in the case of `std::tuple<Args...>` which requires the target
type to be specified by the caller.

Use `InitializerTargetT` to simplify CTAD guides: there is no need to
explicitly exclude `std::tuple`. Make their comments more accurate: passing
`Initializer<T>` to a constructor deduces the template argument as `T`,
not as `Initializer<T>`.

Use `InitializerTargetT` to uniformly handle `Target` passed directly or as
`Initializer<Target>` in functions which deduce the type from an argument:
`MakeAnyText{Reader,Writer}()`.

PiperOrigin-RevId: 623446209
  • Loading branch information
QrczakMK committed Apr 10, 2024
1 parent 669bf3e commit 243b317
Show file tree
Hide file tree
Showing 63 changed files with 337 additions and 632 deletions.
37 changes: 37 additions & 0 deletions riegeli/base/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,43 @@ class Initializer<T, allow_explicit,
}
};

// `InitializerTarget<T>::type` and `InitializerTargetT<T>` deduce the
// appropriate target type such that `T` is convertible to
// `Initializer<InitializerTargetT<T>>`.
//
// This allows a single template to uniformly handle a `Target` passed directly
// or as `Initializer<Target>`. This is also useful for CTAD guides to deduce a
// template argument as `InitializerTargetT<T>`.
//
// This is undefined in the case of `std::tuple<Args...>` which requires the
// target type to be specified by the caller.

namespace initializer_internal {

template <typename T>
struct InitializerTargetImpl {
using type = T;
};

template <typename... Args>
struct InitializerTargetImpl<std::tuple<Args...>> {
// No `type` member when the target type is unspecified.
};

template <typename T>
struct InitializerTargetImpl<Initializer<T>> {
using type = T;
};

}; // namespace initializer_internal

template <typename T>
struct InitializerTarget
: initializer_internal::InitializerTargetImpl<std::decay_t<T>> {};

template <typename T>
using InitializerTargetT = typename InitializerTarget<T>::type;

// Implementation details follow.

namespace initializer_internal {
Expand Down
14 changes: 4 additions & 10 deletions riegeli/brotli/brotli_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#include <stddef.h>

#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
Expand Down Expand Up @@ -144,8 +142,9 @@ class BrotliReaderBase : public PullableReader {
// `ChainReader<>` (owned), `std::unique_ptr<Reader>` (owned),
// `AnyDependency<Reader*>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as the value type of
// the first constructor argument. This requires C++17.
// By relying on CTAD the template argument can be deduced as
// `InitializerTargetT` of the type of the first constructor argument.
// This requires C++17.
//
// The compressed `Reader` must not be accessed until the `BrotliReader` is
// closed or no longer used.
Expand Down Expand Up @@ -189,12 +188,7 @@ explicit BrotliReader(Closed) -> BrotliReader<DeleteCtad<Closed>>;
template <typename Src>
explicit BrotliReader(
Src&& src, BrotliReaderBase::Options options = BrotliReaderBase::Options())
-> BrotliReader<std::decay_t<Src>>;
template <typename... SrcArgs>
explicit BrotliReader(
std::tuple<SrcArgs...> src_args,
BrotliReaderBase::Options options = BrotliReaderBase::Options())
-> BrotliReader<DeleteCtad<std::tuple<SrcArgs...>>>;
-> BrotliReader<InitializerTargetT<Src>>;
#endif

// Implementation details follow.
Expand Down
14 changes: 4 additions & 10 deletions riegeli/brotli/brotli_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
#define RIEGELI_BROTLI_BROTLI_WRITER_H_

#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
Expand Down Expand Up @@ -192,8 +190,9 @@ class BrotliWriterBase : public BufferedWriter {
// `ChainWriter<>` (owned), `std::unique_ptr<Writer>` (owned),
// `AnyDependency<Writer*>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as the value type of
// the first constructor argument. This requires C++17.
// By relying on CTAD the template argument can be deduced as
// `InitializerTargetT` of the type of the first constructor argument.
// This requires C++17.
//
// The compressed `Writer` must not be accessed until the `BrotliWriter` is
// closed or no longer used, except that it is allowed to read the destination
Expand Down Expand Up @@ -237,12 +236,7 @@ explicit BrotliWriter(Closed) -> BrotliWriter<DeleteCtad<Closed>>;
template <typename Dest>
explicit BrotliWriter(Dest&& dest, BrotliWriterBase::Options options =
BrotliWriterBase::Options())
-> BrotliWriter<std::decay_t<Dest>>;
template <typename... DestArgs>
explicit BrotliWriter(
std::tuple<DestArgs...> dest_args,
BrotliWriterBase::Options options = BrotliWriterBase::Options())
-> BrotliWriter<DeleteCtad<std::tuple<DestArgs...>>>;
-> BrotliWriter<InitializerTargetT<Dest>>;
#endif

// Implementation details follow.
Expand Down
1 change: 1 addition & 0 deletions riegeli/bytes/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ cc_library(
"//riegeli/base:assert",
"//riegeli/base:compact_string",
"//riegeli/base:dependency",
"//riegeli/base:initializer",
"//riegeli/base:object",
"@com_google_absl//absl/meta:type_traits",
],
Expand Down
18 changes: 7 additions & 11 deletions riegeli/bytes/array_backward_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

#include <stddef.h>

#include <tuple>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -80,12 +79,12 @@ class ArrayBackwardWriterBase : public PushableBackwardWriter {
// `absl::Span<char>` (not owned, default), `std::string*` (not owned),
// `std::string` (owned), `AnyDependency<absl::Span<char>>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as the value type of
// the first constructor argument, except that CTAD is deleted if the first
// constructor argument is a reference to a type that `absl::Span<char>` would
// be constructible from, other than `absl::Span<char>` itself (to avoid writing
// to an unintentionally separate copy of an existing object). This requires
// C++17.
// By relying on CTAD the template argument can be deduced as
// `InitializerTargetT` of the type of the first constructor argument, except
// that CTAD is deleted if the first constructor argument is a reference to a
// type that `absl::Span<char>` would be constructible from, other than
// `absl::Span<char>` itself (to avoid writing to an unintentionally separate
// copy of an existing object). This requires C++17.
//
// The array must not be destroyed until the `ArrayBackwardWriter` is closed or
// no longer used.
Expand Down Expand Up @@ -145,10 +144,7 @@ explicit ArrayBackwardWriter(Dest&& dest)
std::is_constructible<absl::Span<char>, Dest>,
absl::negation<std::is_pointer<std::remove_reference_t<Dest>>>>::
value,
DeleteCtad<Dest&&>, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit ArrayBackwardWriter(std::tuple<DestArgs...> dest_args)
-> ArrayBackwardWriter<DeleteCtad<std::tuple<DestArgs...>>>;
DeleteCtad<Dest&&>, InitializerTargetT<Dest>>>;
explicit ArrayBackwardWriter(char* dest, size_t size)
-> ArrayBackwardWriter<absl::Span<char>>;
#endif
Expand Down
18 changes: 7 additions & 11 deletions riegeli/bytes/array_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

#include <stddef.h>

#include <tuple>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -100,12 +99,12 @@ class ArrayWriterBase : public PushableWriter {
// `absl::Span<char>` (not owned, default), `std::string*` (not owned),
// `std::string` (owned), `AnyDependency<absl::Span<char>>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as the value type of
// the first constructor argument, except that CTAD is deleted if the first
// constructor argument is a reference to a type that `absl::Span<char>` would
// be constructible from, other than `absl::Span<char>` itself (to avoid writing
// to an unintentionally separate copy of an existing object). This requires
// C++17.
// By relying on CTAD the template argument can be deduced as
// `InitializerTargetT` of the type of the first constructor argument, except
// that CTAD is deleted if the first constructor argument is a reference to a
// type that `absl::Span<char>` would be constructible from, other than
// `absl::Span<char>` itself (to avoid writing to an unintentionally separate
// copy of an existing object). This requires C++17.
//
// The array must not be destroyed until the `ArrayWriter` is closed or no
// longer used.
Expand Down Expand Up @@ -164,10 +163,7 @@ explicit ArrayWriter(Dest&& dest)
std::is_constructible<absl::Span<char>, Dest>,
absl::negation<std::is_pointer<std::remove_reference_t<Dest>>>>::
value,
DeleteCtad<Dest&&>, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit ArrayWriter(std::tuple<DestArgs...> dest_args)
-> ArrayWriter<DeleteCtad<std::tuple<DestArgs...>>>;
DeleteCtad<Dest&&>, InitializerTargetT<Dest>>>;
explicit ArrayWriter(char* dest, size_t size) -> ArrayWriter<absl::Span<char>>;
#endif

Expand Down
12 changes: 4 additions & 8 deletions riegeli/bytes/cfile_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,9 @@ class CFileReaderBase : public BufferedReader {
// `UnownedCFile` (not owned), `AnyDependency<CFileHandle>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as `OwnedCFile` if
// the first constructor argument is a filename or a `FILE*`, otherwise as the
// value type of the first constructor argument. This requires C++17.
// the first constructor argument is a filename or a `FILE*`, otherwise as
// `InitializerTargetT` of the type of the first constructor argument.
// This requires C++17.
//
// Warning: if random access is not supported and the `FILE` is not owned, it
// will have an unpredictable amount of extra data consumed because of
Expand Down Expand Up @@ -349,12 +350,7 @@ explicit CFileReader(
std::is_convertible<Src&&, FILE*>,
std::is_convertible<
Src&&, Initializer<std::string>::AllowingExplicit>>::value,
OwnedCFile, std::decay_t<Src>>>;
template <typename... SrcArgs>
explicit CFileReader(
std::tuple<SrcArgs...> src_args,
CFileReaderBase::Options options = CFileReaderBase::Options())
-> CFileReader<DeleteCtad<std::tuple<SrcArgs...>>>;
OwnedCFile, InitializerTargetT<Src>>>;
#endif

// Implementation details follow.
Expand Down
12 changes: 4 additions & 8 deletions riegeli/bytes/cfile_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,9 @@ class CFileWriterBase : public BufferedWriter {
// `UnownedCFile` (not owned), `AnyDependency<CFileHandle>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as `OwnedCFile` if
// the first constructor argument is a filename or a `FILE*`, otherwise as the
// value type of the first constructor argument. This requires C++17.
// the first constructor argument is a filename or a `FILE*`, otherwise as
// `InitializerTargetT` of the type of the first constructor argument.
// This requires C++17.
//
// Until the `CFileWriter` is closed or no longer used, the `FILE` must not be
// closed nor have its position changed, except that if random access is not
Expand Down Expand Up @@ -451,12 +452,7 @@ explicit CFileWriter(
std::is_convertible<Dest&&, FILE*>,
std::is_convertible<
Dest&&, Initializer<std::string>::AllowingExplicit>>::value,
OwnedCFile, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit CFileWriter(
std::tuple<DestArgs...> dest_args,
CFileWriterBase::Options options = CFileWriterBase::Options())
-> CFileWriter<DeleteCtad<std::tuple<DestArgs...>>>;
OwnedCFile, InitializerTargetT<Dest>>>;
#endif

// Implementation details follow.
Expand Down
15 changes: 5 additions & 10 deletions riegeli/bytes/chain_backward_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ class ChainBackwardWriterBase : public BackwardWriter {
//
// By relying on CTAD the template argument can be deduced as `Chain` if there
// are no constructor arguments or the only argument is `Options`, otherwise as
// the value type of the first constructor argument, except that CTAD is deleted
// if the first constructor argument is a `Chain&` or `const Chain&` (to avoid
// writing to an unintentionally separate copy of an existing object). This
// requires C++17.
// `InitializerTargetT` of the type of the first constructor argument, except
// that CTAD is deleted if the first constructor argument is a `Chain&` or
// `const Chain&` (to avoid writing to an unintentionally separate copy of an
// existing object). This requires C++17.
//
// The `Chain` must not be accessed until the `ChainBackwardWriter` is closed or
// no longer used.
Expand Down Expand Up @@ -231,12 +231,7 @@ explicit ChainBackwardWriter(Dest&& dest,
absl::conjunction<std::is_lvalue_reference<Dest>,
std::is_convertible<std::remove_reference_t<Dest>*,
const Chain*>>::value,
DeleteCtad<Dest&&>, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit ChainBackwardWriter(std::tuple<DestArgs...> dest_args,
ChainBackwardWriterBase::Options options =
ChainBackwardWriterBase::Options())
-> ChainBackwardWriter<DeleteCtad<std::tuple<DestArgs...>>>;
DeleteCtad<Dest&&>, InitializerTargetT<Dest>>>;
explicit ChainBackwardWriter(ChainBackwardWriterBase::Options options =
ChainBackwardWriterBase::Options())
-> ChainBackwardWriter<Chain>;
Expand Down
12 changes: 4 additions & 8 deletions riegeli/bytes/chain_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#include <stddef.h>

#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
Expand Down Expand Up @@ -94,8 +92,9 @@ class ChainReaderBase : public PullableReader {
// `Dependency<const Chain*, Src>`, e.g. `const Chain*` (not owned, default),
// `Chain` (owned), `AnyDependency<const Chain*>` (maybe owned).
//
// By relying on CTAD the template argument can be deduced as the value type of
// the first constructor argument. This requires C++17.
// By relying on CTAD the template argument can be deduced as
// `InitializerTargetT` of the type of the first constructor argument.
// This requires C++17.
//
// The `Chain` must not be changed until the `ChainReader` is closed or no
// longer used.
Expand Down Expand Up @@ -135,10 +134,7 @@ class ChainReader : public ChainReaderBase {
#if __cpp_deduction_guides
explicit ChainReader(Closed) -> ChainReader<DeleteCtad<Closed>>;
template <typename Src>
explicit ChainReader(Src&& src) -> ChainReader<std::decay_t<Src>>;
template <typename... SrcArgs>
explicit ChainReader(std::tuple<SrcArgs...> src_args)
-> ChainReader<DeleteCtad<std::tuple<SrcArgs...>>>;
explicit ChainReader(Src&& src) -> ChainReader<InitializerTargetT<Src>>;
#endif

// Implementation details follow.
Expand Down
15 changes: 5 additions & 10 deletions riegeli/bytes/chain_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ class ChainWriterBase : public Writer {
//
// By relying on CTAD the template argument can be deduced as `Chain` if there
// are no constructor arguments or the only argument is `Options`, otherwise as
// the value type of the first constructor argument, except that CTAD is deleted
// if the first constructor argument is a `Chain&` or `const Chain&` (to avoid
// writing to an unintentionally separate copy of an existing object). This
// requires C++17.
// `InitializerTargetT` of the type of the first constructor argument, except
// that CTAD is deleted if the first constructor argument is a `Chain&` or
// `const Chain&` (to avoid writing to an unintentionally separate copy of an
// existing object). This requires C++17.
//
// The `Chain` must not be accessed until the `ChainWriter` is closed or no
// longer used, except that it is allowed to read the `Chain` immediately after
Expand Down Expand Up @@ -288,12 +288,7 @@ explicit ChainWriter(
absl::conjunction<std::is_lvalue_reference<Dest>,
std::is_convertible<std::remove_reference_t<Dest>*,
const Chain*>>::value,
DeleteCtad<Dest&&>, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit ChainWriter(
std::tuple<DestArgs...> dest_args,
ChainWriterBase::Options options = ChainWriterBase::Options())
-> ChainWriter<DeleteCtad<std::tuple<DestArgs...>>>;
DeleteCtad<Dest&&>, InitializerTargetT<Dest>>>;
explicit ChainWriter(ChainWriterBase::Options options =
ChainWriterBase::Options()) -> ChainWriter<Chain>;
#endif
Expand Down
17 changes: 6 additions & 11 deletions riegeli/bytes/compact_string_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

#include <stddef.h>

#include <tuple>
#include <type_traits>

#include "absl/meta/type_traits.h"
#include "riegeli/base/assert.h"
#include "riegeli/base/compact_string.h"
#include "riegeli/base/dependency.h"
#include "riegeli/base/initializer.h"
#include "riegeli/base/object.h"
#include "riegeli/bytes/resizable_writer.h"

Expand Down Expand Up @@ -80,10 +80,10 @@ using CompactStringWriterBase = ResizableWriterBase;
//
// By relying on CTAD the template argument can be deduced as `CompactString`
// if there are no constructor arguments or the only argument is `Options`,
// otherwise as the value type of the first constructor argument, except that
// CTAD is deleted if the first constructor argument is a `CompactString&` or
// `const CompactString&` (to avoid writing to an unintentionally separate copy
// of an existing object). This requires C++17.
// otherwise as `InitializerTargetT` of the type of the first constructor
// argument, except that CTAD is deleted if the first constructor argument is a
// `CompactString&` or `const CompactString&` (to avoid writing to an
// unintentionally separate copy of an existing object). This requires C++17.
//
// The `CompactString` must not be accessed until the `CompactStringWriter` is
// closed or no longer used, except that it is allowed to read the
Expand All @@ -106,12 +106,7 @@ explicit CompactStringWriter(Dest&& dest,
absl::conjunction<std::is_lvalue_reference<Dest>,
std::is_convertible<std::remove_reference_t<Dest>*,
const CompactString*>>::value,
DeleteCtad<Dest&&>, std::decay_t<Dest>>>;
template <typename... DestArgs>
explicit CompactStringWriter(std::tuple<DestArgs...> dest_args,
CompactStringWriterBase::Options options =
CompactStringWriterBase::Options())
-> CompactStringWriter<DeleteCtad<std::tuple<DestArgs...>>>;
DeleteCtad<Dest&&>, InitializerTargetT<Dest>>>;
explicit CompactStringWriter(CompactStringWriterBase::Options options =
CompactStringWriterBase::Options())
-> CompactStringWriter<CompactString>;
Expand Down
Loading

0 comments on commit 243b317

Please sign in to comment.