Allow generators to declare themselves (infinite)

This will be useful later to implement warning on infinitely
running `GENERATE` expressions.
This commit is contained in:
Martin Hořeňovský committed 2026-02-10 09:37:15 +01:00
1 parent 0056cd4efb
commit d079ee13ab
31 files changed
+869 -18

No files matched your search

@@ -64,6 +64,8 @@ namespace Detail {
bool next() {
return m_generator->countedNext();
}
bool isFinite() const { return m_generator->isFinite(); }
};
@@ -84,6 +86,8 @@ namespace Detail {
bool next() override {
return false;
}
bool isFinite() const override { return true; }
};
template<typename T>
@@ -112,6 +116,8 @@ namespace Detail {
++m_idx;
return m_idx < m_values.size();
}
bool isFinite() const override { return true; }
};
template <typename T, typename DecayedT = std::decay_t<T>>
@@ -176,6 +182,14 @@ namespace Detail {
}
return m_current < m_generators.size();
}
bool isFinite() const override {
for (auto const& gen : m_generators) {
if (!gen.isFinite()) { return false;
}
}
return true;
}
};
@@ -62,6 +62,8 @@ namespace Generators {
}
return success;
}
bool isFinite() const override { return true; }
};
template <typename T>
@@ -103,6 +105,8 @@ namespace Generators {
while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
return success;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
@@ -127,6 +131,9 @@ namespace Generators {
m_target_repeats(repeats)
{
assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
if (!m_generator.isFinite()) {
Detail::throw_generator_exception( "Cannot repeat infinite generator" );
}
}
T const& get() const override {
@@ -160,6 +167,8 @@ namespace Generators {
}
return m_current_repeat < m_target_repeats;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename T>
@@ -207,6 +216,8 @@ namespace Generators {
}
return success;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
@@ -256,6 +267,8 @@ namespace Generators {
}
return true;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename T>
@@ -297,6 +310,13 @@ namespace Generators {
++m_current_generator;
return m_current_generator < m_generators.size();
}
bool isFinite() const override {
for ( auto const& gen : m_generators ) {
if ( !gen.isFinite() ) { return false; }
}
return true;
}
};
template <typename T, typename... Generators>
@@ -37,5 +37,10 @@ namespace Catch {
m_current_number = m_pimpl->dist( m_pimpl->rng );
return true;
}
bool RandomFloatingGenerator<long double>::isFinite() const {
return false;
}
} // namespace Generators
} // namespace Catch
@@ -42,6 +42,7 @@ public:
m_current_number = m_dist(m_rng);
return true;
}
bool isFinite() const override { return false; }
};
template <>
@@ -59,6 +60,7 @@ public:
bool next() override;
~RandomFloatingGenerator() override; // = default
bool isFinite() const override;
};
template <typename Integer>
@@ -80,6 +82,7 @@ public:
m_current_number = m_dist(m_rng);
return true;
}
bool isFinite() const override { return false; }
};
template <typename T>
@@ -48,6 +48,8 @@ public:
m_current += m_step;
return (m_positive) ? (m_current < m_end) : (m_current > m_end);
}
bool isFinite() const override { return true; }
};
template <typename T>
@@ -87,6 +89,8 @@ public:
++m_current;
return m_current != m_elems.size();
}
bool isFinite() const override { return true; }
};
template <typename InputIterator,
@@ -55,5 +55,7 @@ namespace Catch {
return m_stringReprCache;
}
bool GeneratorUntypedBase::isFinite() const { return true; }
} // namespace Generators
} // namespace Catch
@@ -88,6 +88,15 @@ namespace Catch {
* comes first.
*/
StringRef currentElementAsString() const;
/**
* Returns true if calls to `next` will eventually return false
*
* Note that for backwards compatibility this is currently defaulted
* to return `true`, but in the future all generators will have to
* provide their own implementation.
*/
virtual bool isFinite() const;
};
using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;