7#ifndef TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
8#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
23class GeneratorException :
public std::exception {
24 const char*
const m_msg =
"";
31 const char*
what() const noexcept override final;
38 template<
typename T,
typename... Args>
40 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
45 struct IGenerator : GeneratorUntypedBase {
52 virtual T const&
get()
const = 0;
63 T const&
get()
const override {
72 class FixedValuesGenerator final :
public IGenerator<T> {
73 std::vector<T> m_values;
78 T const&
get()
const override {
79 return m_values[m_idx];
83 return m_idx < m_values.size();
88 class GeneratorWrapper final {
89 std::unique_ptr<IGenerator<T>> m_generator;
92 m_generator(
std::move(generator))
95 return m_generator->get();
98 return m_generator->next();
102 template <
typename T>
106 template <
typename T>
112 class Generators :
public IGenerator<T> {
113 std::vector<GeneratorWrapper<T>> m_generators;
114 size_t m_current = 0;
116 void populate(GeneratorWrapper<T>&& generator) {
117 m_generators.emplace_back(std::move(generator));
119 void populate(
T&& val) {
120 m_generators.emplace_back(
value(std::move(val)));
123 void populate(
U&& val) {
124 populate(
T(std::move(val)));
126 template<
typename U,
typename... Gs>
127 void populate(
U&& valueOrGenerator, Gs... moreGenerators) {
128 populate(std::forward<U>(valueOrGenerator));
129 populate(std::forward<Gs>(moreGenerators)...);
133 template <
typename... Gs>
135 m_generators.reserve(
sizeof...(Gs));
136 populate(std::forward<Gs>(moreGenerators)...);
139 T const&
get()
const override {
140 return m_generators[m_current].get();
144 if (m_current >= m_generators.size()) {
147 const bool current_status = m_generators[m_current].next();
148 if (!current_status) {
151 return m_current < m_generators.size();
156 template<
typename... Ts>
157 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<
typename std::decay<Ts>::type...>> tuples ) {
158 return values<std::tuple<Ts...>>( tuples );
162 template <
typename T>
165 template<
typename T,
typename... Gs>
167 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
173 template<
typename T,
typename... Gs>
175 return makeGenerators(
value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
177 template<
typename T,
typename U,
typename... Gs>
179 return makeGenerators(
value(
T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
188 auto generate(
SourceLineInfo const& lineInfo, L
const& generatorExpression ) ->
decltype(std::declval<decltype(generatorExpression())>().get()) {
189 using UnderlyingType =
typename decltype(generatorExpression())::type;
197 return generator.get();
203#define GENERATE( ... ) \
204 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
205#define GENERATE_COPY( ... ) \
206 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
207#define GENERATE_REF( ... ) \
208 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
GeneratorException(const char *msg)
const char * what() const noexcept override final
FixedValuesGenerator(std::initializer_list< T > values)
T const & get() const override
GeneratorWrapper(std::unique_ptr< IGenerator< T > > generator)
Generators(Gs... moreGenerators)
T const & get() const override
SingleValueGenerator(T const &value)
SingleValueGenerator(T &&value)
T const & get() const override
std::unique_ptr< T > make_unique(Args &&... args)
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &
auto makeGenerators(GeneratorWrapper< T > &&generator, Gs... moreGenerators) -> Generators< T >
auto generate(SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
GeneratorWrapper< T > values(std::initializer_list< T > values)
#define T(meth, val, expected)
virtual T const & get() const =0
virtual ~IGenerator()=default
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const &=0
virtual void setGenerator(Generators::GeneratorBasePtr &&generator)=0
virtual auto hasGenerator() const -> bool=0