Merge pull request #6 from bkryza/add-template-overload-pattern-test-case

Add template overload pattern test case
This commit is contained in:
Bartek Kryza
2021-08-04 00:00:17 +02:00
committed by GitHub
39 changed files with 434 additions and 154 deletions

View File

@@ -62,4 +62,4 @@ init_compile_commands: debug
.PHONY: clang-format .PHONY: clang-format
clang-format: clang-format:
docker run --rm -v $(CURDIR):/root/sources bkryza/clang-format-check:1.2 docker run --rm -v $(CURDIR):/root/sources bkryza/clang-format-check:1.3

View File

@@ -163,6 +163,17 @@ The following decorators are currently supported:
- [aggregation](docs/test_cases/t00030.md) - document the property as aggregation - [aggregation](docs/test_cases/t00030.md) - document the property as aggregation
- [style](docs/test_cases/t00031.md) - add PlantUML style to a C++ entity - [style](docs/test_cases/t00031.md) - add PlantUML style to a C++ entity
##### Doxygen integration
`clang-uml` can be omitted completed in ![Doxygen](https://www.doxygen.nl/index.html), by adding the following
lines to the Doxygen config file:
```
ALIASES += clanguml=""
ALIASES += clanguml{1}=""
ALIASES += clanguml{2}=""
ALIASES += clanguml{3}=""
```
### Sequence diagrams ### Sequence diagrams
#### Example #### Example

View File

@@ -30,6 +30,7 @@
* [t00029](./test_cases/t00029.md) - PlantUML skip decorator test case * [t00029](./test_cases/t00029.md) - PlantUML skip decorator test case
* [t00030](./test_cases/t00030.md) - PlantUML relationship decorators test case * [t00030](./test_cases/t00030.md) - PlantUML relationship decorators test case
* [t00031](./test_cases/t00031.md) - PlantUML style decorator test case * [t00031](./test_cases/t00031.md) - PlantUML style decorator test case
* [t00032](./test_cases/t00032.md) - Class template with template base classes test case
## Sequence diagrams ## Sequence diagrams
* [t20001](./test_cases/t20001.md) - Basic sequence diagram * [t20001](./test_cases/t20001.md) - Basic sequence diagram
## Configuration diagrams ## Configuration diagrams

View File

@@ -34,12 +34,12 @@ public:
class B : public A { class B : public A {
public: public:
virtual void foo_a() override {} virtual void foo_a() override { }
}; };
class C : public A { class C : public A {
public: public:
virtual void foo_c() override {} virtual void foo_c() override { }
}; };
class D : public B, public C { class D : public B, public C {

View File

@@ -35,9 +35,9 @@ public:
A(const A &) = default; A(const A &) = default;
virtual ~A() = default; virtual ~A() = default;
void basic_method() {} void basic_method() { }
static int static_method() { return 0; } static int static_method() { return 0; }
void const_method() const {} void const_method() const { }
auto auto_method() { return 1; } auto auto_method() { return 1; }
auto double_int(const int i) { return 2 * i; } auto double_int(const int i) { return 2 * i; }
@@ -57,7 +57,7 @@ public:
static const auto auto_member{10UL}; static const auto auto_member{10UL};
protected: protected:
void protected_method() {} void protected_method() { }
int protected_member; int protected_member;
@@ -66,7 +66,7 @@ protected:
}; };
private: private:
void private_method() {} void private_method() { }
int private_member; int private_member;
int a, b, c; int a, b, c;

View File

@@ -25,7 +25,7 @@ namespace t00004 {
class A { class A {
public: public:
void foo() const {} void foo() const { }
class AA { class AA {
public: public:
@@ -35,7 +35,7 @@ public:
}; };
}; };
void foo2() const {} void foo2() const { }
}; };
} }
} }

View File

@@ -34,7 +34,7 @@ template <typename T> class D {
class A { class A {
private: private:
void foo() {} void foo() { }
friend class B; friend class B;
friend class external::C; friend class external::C;
// TODO // TODO

View File

@@ -48,7 +48,7 @@ class R;
struct D { struct D {
int d; int d;
void print(R *r) {} void print(R *r) { }
}; };
template <typename T> struct E { template <typename T> struct E {

View File

@@ -28,7 +28,8 @@ class A {
} }
namespace ns2_v0_9_0 { namespace ns2_v0_9_0 {
class [[deprecated]] A {}; class [[deprecated]] A {
};
} }
namespace { namespace {

View File

@@ -35,20 +35,20 @@ public:
class Visitor1 : public Visitor { class Visitor1 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Visitor2 : public Visitor { class Visitor2 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Visitor3 : public Visitor { class Visitor3 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Item { class Item {
@@ -59,12 +59,12 @@ public:
class A : public Item { class A : public Item {
public: public:
void accept(const Visitor &visitor) const override {} void accept(const Visitor &visitor) const override { }
}; };
class B : public Item { class B : public Item {
public: public:
void accept(const Visitor &visitor) const override {} void accept(const Visitor &visitor) const override { }
}; };
} }
} }

View File

@@ -38,14 +38,14 @@ protected:
class A1 : public A { class A1 : public A {
protected: protected:
void method1() override {} void method1() override { }
void method2() override {} void method2() override { }
}; };
class A2 : public A { class A2 : public A {
protected: protected:
void method1() override {} void method1() override { }
void method2() override {} void method2() override { }
}; };
} }
} }

View File

@@ -31,17 +31,17 @@ public:
class StrategyA : public Strategy { class StrategyA : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class StrategyB : public Strategy { class StrategyB : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class StrategyC : public Strategy { class StrategyC : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class Context { class Context {

View File

@@ -33,14 +33,14 @@ public:
class Target1 : public Target { class Target1 : public Target {
public: public:
void m1() override {} void m1() override { }
void m2() override {} void m2() override { }
}; };
class Target2 : public Target { class Target2 : public Target {
public: public:
void m1() override {} void m1() override { }
void m2() override {} void m2() override { }
}; };
class Proxy : public Target { class Proxy : public Target {

View File

@@ -25,14 +25,14 @@ namespace t00025 {
class Target1 { class Target1 {
public: public:
void m1() {} void m1() { }
void m2() {} void m2() { }
}; };
class Target2 { class Target2 {
public: public:
void m1() {} void m1() { }
void m2() {} void m2() { }
}; };
template <typename T> class Proxy { template <typename T> class Proxy {

View File

@@ -36,7 +36,7 @@ class Line : public Shape, public T<Line<>>... {
public: public:
void display() override void display() override
{ {
std::apply([](auto &&... x) { (x.display(), ...); }, std::apply([](auto &&...x) { (x.display(), ...); },
std::forward_as_tuple(T<Line<>>()...)); std::forward_as_tuple(T<Line<>>()...));
} }
}; };
@@ -46,7 +46,7 @@ class Text : public Shape, public T<Text<>>... {
public: public:
void display() override void display() override
{ {
std::apply([](auto &&... x) { (x.display(), ...); }, std::apply([](auto &&...x) { (x.display(), ...); },
std::forward_as_tuple(T<Text<>>()...)); std::forward_as_tuple(T<Text<>>()...));
} }
}; };
@@ -57,12 +57,12 @@ struct ShapeDecorator {
template <typename T> class Color : public ShapeDecorator { template <typename T> class Color : public ShapeDecorator {
public: public:
void display() override {} void display() override { }
}; };
template <typename T> class Weight : public ShapeDecorator { template <typename T> class Weight : public ShapeDecorator {
public: public:
void display() override {} void display() override { }
}; };
struct Window { struct Window {

62
docs/test_cases/t00032.md Normal file
View File

@@ -0,0 +1,62 @@
# t00032 - Class template with template base classes test case
## Config
```yaml
compilation_database_dir: ..
output_directory: puml
diagrams:
t00032_class:
type: class
glob:
- ../../tests/t00032/t00032.cc
using_namespace:
- clanguml::t00032
include:
namespaces:
- clanguml::t00032
```
## Source code
File t00032.cc
```cpp
#include <memory>
#include <vector>
namespace clanguml {
namespace t00032 {
struct Base {
};
struct TBase {
};
struct A {
void operator()() { }
};
struct B {
void operator()() { }
};
struct C {
void operator()() { }
};
template <typename T, typename L, typename... Ts>
struct Overload : public Base, public T, public Ts... {
using Ts::operator()...;
L counter;
};
template <class... Ts> Overload(Ts...) -> Overload<Ts...>;
struct R {
Overload<TBase, int, A, B, C> overload;
};
} // namespace t00032
} // namespace clanguml
```
## Generated UML diagrams
![t00032_class](./t00032_class.png "Class template with template base classes test case")

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -43,7 +43,7 @@ struct C {
class A { class A {
public: public:
A() {} A() { }
int add(int x, int y) { return m_c.add(x, y); } int add(int x, int y) { return m_c.add(x, y); }
@@ -58,7 +58,7 @@ public:
return res; return res;
} }
void log_result(int r) {} void log_result(int r) { }
private: private:
detail::C m_c{}; detail::C m_c{};

View File

@@ -31,6 +31,8 @@
#include <cppast/cpp_variable.hpp> #include <cppast/cpp_variable.hpp>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <deque>
namespace clanguml { namespace clanguml {
namespace visitor { namespace visitor {
namespace class_diagram { namespace class_diagram {
@@ -1185,6 +1187,8 @@ class_ tu_visitor::build_template_instantiation(
class_ tinst; class_ tinst;
std::string full_template_name; std::string full_template_name;
std::deque<std::tuple<std::string, int, bool>> template_base_params{};
if (t.primary_template().get(ctx.entity_index).size()) { if (t.primary_template().get(ctx.entity_index).size()) {
const auto &primary_template_ref = const auto &primary_template_ref =
static_cast<const cppast::cpp_class_template &>( static_cast<const cppast::cpp_class_template &>(
@@ -1201,6 +1205,54 @@ class_ tu_visitor::build_template_instantiation(
if (full_template_name.back() == ':') if (full_template_name.back() == ':')
tinst.name = full_template_name + tinst.name; tinst.name = full_template_name + tinst.name;
std::vector<std::pair<std::string, bool>> template_parameter_names{};
if (primary_template_ref.scope_name().has_value()) {
for (const auto &tp : primary_template_ref.scope_name()
.value()
.template_parameters()) {
template_parameter_names.emplace_back(
tp.name(), tp.is_variadic());
}
}
// Check if the primary template has any base classes
int base_index = 0;
for (const auto &base : primary_template_ref.bases()) {
if (base.kind() == cppast::cpp_entity_kind::base_class_t) {
const auto &base_class =
static_cast<const cppast::cpp_base_class &>(base);
const auto base_class_name =
cppast::to_string(base_class.type());
LOG_DBG("Found template instantiation base: {}, {}, {}",
cppast::to_string(base.kind()), base_class_name,
base_index);
// Check if any of the primary template arguments has a
// parameter equal to this type
auto it = std::find_if(template_parameter_names.begin(),
template_parameter_names.end(),
[&base_class_name](
const auto &p) { return p.first == base_class_name; });
if (it != template_parameter_names.end()) {
// Found base class which is a template parameter
LOG_DBG("Found base class which is a template parameter "
"{}, {}, {}",
it->first, it->second,
std::distance(template_parameter_names.begin(), it));
template_base_params.emplace_back(it->first, it->second,
std::distance(template_parameter_names.begin(), it));
}
else {
// This is a regular base class - it is handled by
// process_template
}
}
base_index++;
}
if (primary_template_ref.user_data()) { if (primary_template_ref.user_data()) {
tinst.base_template_usr = tinst.base_template_usr =
static_cast<const char *>(primary_template_ref.user_data()); static_cast<const char *>(primary_template_ref.user_data());
@@ -1232,7 +1284,11 @@ class_ tu_visitor::build_template_instantiation(
tinst.is_template_instantiation = true; tinst.is_template_instantiation = true;
// Process template argumetns
int arg_index{0};
bool variadic_params{false};
for (const auto &targ : t.arguments().value()) { for (const auto &targ : t.arguments().value()) {
bool add_template_argument_as_base_class{false};
class_template ct; class_template ct;
if (targ.type()) { if (targ.type()) {
ct.type = cppast::to_string(targ.type().value()); ct.type = cppast::to_string(targ.type().value());
@@ -1250,6 +1306,31 @@ class_ tu_visitor::build_template_instantiation(
.as_string(); .as_string();
} }
// In case any of the template arguments are base classes, add
// them as parents of the current template instantiation class
if (template_base_params.size() > 0) {
auto [arg_name, is_variadic, index] = template_base_params.front();
if (variadic_params)
add_template_argument_as_base_class = true;
else {
variadic_params = is_variadic;
if (arg_index == index) {
add_template_argument_as_base_class = true;
template_base_params.pop_front();
}
}
if (add_template_argument_as_base_class) {
LOG_DBG("Adding template argument '{}' as base class", ct.type);
class_parent cp;
cp.access = class_parent::access_t::kPublic;
cp.name = ct.type;
tinst.bases.emplace_back(std::move(cp));
}
}
LOG_DBG("Adding template argument '{}'", ct.type); LOG_DBG("Adding template argument '{}'", ct.type);
tinst.templates.emplace_back(std::move(ct)); tinst.templates.emplace_back(std::move(ct));

View File

@@ -55,7 +55,7 @@ struct diagram {
std::map<std::string, activity> sequences; std::map<std::string, activity> sequences;
void sort() {} void sort() { }
}; };
} }
} }

View File

@@ -853,8 +853,9 @@ constexpr auto operator"" _catch_sr(
INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
#else #else
#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \
INTERNAL_CATCH_EXPAND_VARGS(decltype( \ INTERNAL_CATCH_EXPAND_VARGS( \
get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN( \
__VA_ARGS__)>()))
#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \
INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2( \ INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2( \
INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
@@ -1277,8 +1278,8 @@ template <typename> struct true_given : std::true_type {
}; };
struct is_callable_tester { struct is_callable_tester {
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
true_given<decltype( true_given<decltype(std::declval<Fun>()(
std::declval<Fun>()(std::declval<Args>()...))> static test(int); std::declval<Args>()...))> static test(int);
template <typename...> std::false_type static test(...); template <typename...> std::false_type static test(...);
}; };
@@ -1634,8 +1635,8 @@ struct AutoReg : NonCopyable {
}; \ }; \
static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
using TestInit = typename create<TestName, \ using TestInit = typename create<TestName, \
decltype( \ decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS( \
get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), \ TmplTypes)>()), \
TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES( \ TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES( \
INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
TestInit t; \ TestInit t; \
@@ -1851,8 +1852,8 @@ struct AutoReg : NonCopyable {
}; \ }; \
static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
using TestInit = typename create<TestNameClass, \ using TestInit = typename create<TestNameClass, \
decltype( \ decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS( \
get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), \ TmplTypes)>()), \
TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES( \ TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES( \
INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
TestInit t; \ TestInit t; \
@@ -2152,7 +2153,7 @@ inline id performOptionalSelector(id obj, SEL sel)
#define CATCH_UNSAFE_UNRETAINED #define CATCH_UNSAFE_UNRETAINED
#define CATCH_ARC_STRONG #define CATCH_ARC_STRONG
#else #else
inline void arcSafeRelease(NSObject *) {} inline void arcSafeRelease(NSObject *) { }
inline id performOptionalSelector(id obj, SEL sel) inline id performOptionalSelector(id obj, SEL sel)
{ {
#ifdef __clang__ #ifdef __clang__
@@ -2194,8 +2195,9 @@ template <typename T> std::string rawMemoryToString(const T &object)
template <typename T> class IsStreamInsertable { template <typename T> class IsStreamInsertable {
template <typename Stream, typename U> template <typename Stream, typename U>
static auto test(int) -> decltype( static auto test(int)
std::declval<Stream &>() << std::declval<U>(), std::true_type()); -> decltype(std::declval<Stream &>() << std::declval<U>(),
std::true_type());
template <typename, typename> static auto test(...) -> std::false_type; template <typename, typename> static auto test(...) -> std::false_type;
@@ -2549,7 +2551,7 @@ struct TupleElementPrinter {
template <typename Tuple, std::size_t N> template <typename Tuple, std::size_t N>
struct TupleElementPrinter<Tuple, N, false> { struct TupleElementPrinter<Tuple, N, false> {
static void print(const Tuple &, std::ostream &) {} static void print(const Tuple &, std::ostream &) { }
}; };
} }
@@ -3318,7 +3320,7 @@ public:
} }
template <typename T, typename... Ts> template <typename T, typename... Ts>
void captureValues(size_t index, T const &value, Ts const &... values) void captureValues(size_t index, T const &value, Ts const &...values)
{ {
captureValue(index, Catch::Detail::stringify(value)); captureValue(index, Catch::Detail::stringify(value));
captureValues(index + 1, values...); captureValues(index + 1, values...);
@@ -4698,13 +4700,15 @@ struct IGeneratorTracker {
namespace Catch { namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
template <typename Ex> template <typename Ex> [[noreturn]] void throw_exception(Ex const &e)
[[noreturn]] void throw_exception(Ex const &e) { throw e; } {
throw e;
}
#else // ^^ Exceptions are enabled // Exceptions are disabled vv #else // ^^ Exceptions are enabled // Exceptions are disabled vv
[[noreturn]] void throw_exception(std::exception const &e); [[noreturn]] void throw_exception(std::exception const &e);
#endif #endif
[[noreturn]] void throw_logic_error(std::string const &msg); [[noreturn]] void throw_logic_error(std::string const &msg);
[[noreturn]] void throw_domain_error(std::string const &msg); [[noreturn]] void throw_domain_error(std::string const &msg);
[[noreturn]] void throw_runtime_error(std::string const &msg); [[noreturn]] void throw_runtime_error(std::string const &msg);
@@ -4754,7 +4758,7 @@ namespace Generators {
// !TBD move this into its own location? // !TBD move this into its own location?
namespace pf { namespace pf {
template <typename T, typename... Args> template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args &&... args) std::unique_ptr<T> make_unique(Args &&...args)
{ {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
@@ -4847,14 +4851,14 @@ template <typename T> class Generators : public IGenerator<T> {
populate(T(std::forward<U>(val))); populate(T(std::forward<U>(val)));
} }
template <typename U, typename... Gs> template <typename U, typename... Gs>
void populate(U &&valueOrGenerator, Gs &&... moreGenerators) void populate(U &&valueOrGenerator, Gs &&...moreGenerators)
{ {
populate(std::forward<U>(valueOrGenerator)); populate(std::forward<U>(valueOrGenerator));
populate(std::forward<Gs>(moreGenerators)...); populate(std::forward<Gs>(moreGenerators)...);
} }
public: public:
template <typename... Gs> Generators(Gs &&... moreGenerators) template <typename... Gs> Generators(Gs &&...moreGenerators)
{ {
m_generators.reserve(sizeof...(Gs)); m_generators.reserve(sizeof...(Gs));
populate(std::forward<Gs>(moreGenerators)...); populate(std::forward<Gs>(moreGenerators)...);
@@ -4888,7 +4892,7 @@ template <typename T> struct as {
}; };
template <typename T, typename... Gs> template <typename T, typename... Gs>
auto makeGenerators(GeneratorWrapper<T> &&generator, Gs &&... moreGenerators) auto makeGenerators(GeneratorWrapper<T> &&generator, Gs &&...moreGenerators)
-> Generators<T> -> Generators<T>
{ {
return Generators<T>( return Generators<T>(
@@ -4900,13 +4904,13 @@ auto makeGenerators(GeneratorWrapper<T> &&generator) -> Generators<T>
return Generators<T>(std::move(generator)); return Generators<T>(std::move(generator));
} }
template <typename T, typename... Gs> template <typename T, typename... Gs>
auto makeGenerators(T &&val, Gs &&... moreGenerators) -> Generators<T> auto makeGenerators(T &&val, Gs &&...moreGenerators) -> Generators<T>
{ {
return makeGenerators( return makeGenerators(
value(std::forward<T>(val)), std::forward<Gs>(moreGenerators)...); value(std::forward<T>(val)), std::forward<Gs>(moreGenerators)...);
} }
template <typename T, typename U, typename... Gs> template <typename T, typename U, typename... Gs>
auto makeGenerators(as<T>, U &&val, Gs &&... moreGenerators) -> Generators<T> auto makeGenerators(as<T>, U &&val, Gs &&...moreGenerators) -> Generators<T>
{ {
return makeGenerators( return makeGenerators(
value(T(std::forward<U>(val))), std::forward<Gs>(moreGenerators)...); value(T(std::forward<U>(val))), std::forward<Gs>(moreGenerators)...);
@@ -5749,7 +5753,7 @@ public:
} }
private: private:
virtual ~OcMethod() {} virtual ~OcMethod() { }
Class m_cls; Class m_cls;
SEL m_sel; SEL m_sel;
@@ -6557,7 +6561,7 @@ struct IStreamingReporter {
virtual void noMatchingTestCases(std::string const &spec) = 0; virtual void noMatchingTestCases(std::string const &spec) = 0;
virtual void reportInvalidArguments(std::string const &) {} virtual void reportInvalidArguments(std::string const &) { }
virtual void testRunStarting(TestRunInfo const &testRunInfo) = 0; virtual void testRunStarting(TestRunInfo const &testRunInfo) = 0;
virtual void testGroupStarting(GroupInfo const &groupInfo) = 0; virtual void testGroupStarting(GroupInfo const &groupInfo) = 0;
@@ -6566,10 +6570,10 @@ struct IStreamingReporter {
virtual void sectionStarting(SectionInfo const &sectionInfo) = 0; virtual void sectionStarting(SectionInfo const &sectionInfo) = 0;
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
virtual void benchmarkPreparing(std::string const &) {} virtual void benchmarkPreparing(std::string const &) { }
virtual void benchmarkStarting(BenchmarkInfo const &) {} virtual void benchmarkStarting(BenchmarkInfo const &) { }
virtual void benchmarkEnded(BenchmarkStats<> const &) {} virtual void benchmarkEnded(BenchmarkStats<> const &) { }
virtual void benchmarkFailed(std::string const &) {} virtual void benchmarkFailed(std::string const &) { }
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
virtual void assertionStarting(AssertionInfo const &assertionInfo) = 0; virtual void assertionStarting(AssertionInfo const &assertionInfo) = 0;
@@ -6652,9 +6656,9 @@ template <typename DerivedT> struct StreamingReporterBase : IStreamingReporter {
~StreamingReporterBase() override = default; ~StreamingReporterBase() override = default;
void noMatchingTestCases(std::string const &) override {} void noMatchingTestCases(std::string const &) override { }
void reportInvalidArguments(std::string const &) override {} void reportInvalidArguments(std::string const &) override { }
void testRunStarting(TestRunInfo const &_testRunInfo) override void testRunStarting(TestRunInfo const &_testRunInfo) override
{ {
@@ -6718,7 +6722,7 @@ struct CumulativeReporterBase : IStreamingReporter {
: value(_value) : value(_value)
{ {
} }
virtual ~Node() {} virtual ~Node() { }
using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
T value; T value;
@@ -6794,10 +6798,10 @@ struct CumulativeReporterBase : IStreamingReporter {
return {Verbosity::Normal}; return {Verbosity::Normal};
} }
void testRunStarting(TestRunInfo const &) override {} void testRunStarting(TestRunInfo const &) override { }
void testGroupStarting(GroupInfo const &) override {} void testGroupStarting(GroupInfo const &) override { }
void testCaseStarting(TestCaseInfo const &) override {} void testCaseStarting(TestCaseInfo const &) override { }
void sectionStarting(SectionInfo const &sectionInfo) override void sectionStarting(SectionInfo const &sectionInfo) override
{ {
@@ -6823,7 +6827,7 @@ struct CumulativeReporterBase : IStreamingReporter {
m_deepestSection = std::move(node); m_deepestSection = std::move(node);
} }
void assertionStarting(AssertionInfo const &) override {} void assertionStarting(AssertionInfo const &) override { }
bool assertionEnded(AssertionStats const &assertionStats) override bool assertionEnded(AssertionStats const &assertionStats) override
{ {
@@ -6873,7 +6877,7 @@ struct CumulativeReporterBase : IStreamingReporter {
} }
virtual void testRunEndedCumulative() = 0; virtual void testRunEndedCumulative() = 0;
void skipTest(TestCaseInfo const &) override {} void skipTest(TestCaseInfo const &) override { }
IConfigPtr m_config; IConfigPtr m_config;
std::ostream &stream; std::ostream &stream;
@@ -7458,7 +7462,7 @@ inline void optimizer_barrier()
template <typename T> inline void deoptimize_value(T &&x) { keep_memory(&x); } template <typename T> inline void deoptimize_value(T &&x) { keep_memory(&x); }
template <typename Fn, typename... Args> template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn &&fn, Args &&... args) -> inline auto invoke_deoptimized(Fn &&fn, Args &&...args) ->
typename std::enable_if< typename std::enable_if<
!std::is_same<void, decltype(fn(args...))>::value>::type !std::is_same<void, decltype(fn(args...))>::value>::type
{ {
@@ -7466,7 +7470,7 @@ inline auto invoke_deoptimized(Fn &&fn, Args &&... args) ->
} }
template <typename Fn, typename... Args> template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn &&fn, Args &&... args) -> inline auto invoke_deoptimized(Fn &&fn, Args &&...args) ->
typename std::enable_if< typename std::enable_if<
std::is_same<void, decltype(fn(args...))>::value>::type std::is_same<void, decltype(fn(args...))>::value>::type
{ {
@@ -7498,14 +7502,14 @@ template <typename T> using CompleteType_t = typename CompleteType<T>::type;
template <typename Result> struct CompleteInvoker { template <typename Result> struct CompleteInvoker {
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
static Result invoke(Fun &&fun, Args &&... args) static Result invoke(Fun &&fun, Args &&...args)
{ {
return std::forward<Fun>(fun)(std::forward<Args>(args)...); return std::forward<Fun>(fun)(std::forward<Args>(args)...);
} }
}; };
template <> struct CompleteInvoker<void> { template <> struct CompleteInvoker<void> {
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
static CompleteType_t<void> invoke(Fun &&fun, Args &&... args) static CompleteType_t<void> invoke(Fun &&fun, Args &&...args)
{ {
std::forward<Fun>(fun)(std::forward<Args>(args)...); std::forward<Fun>(fun)(std::forward<Args>(args)...);
return {}; return {};
@@ -7516,7 +7520,7 @@ template <typename Sig> using ResultOf_t = typename std::result_of<Sig>::type;
// invoke and not return void :( // invoke and not return void :(
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke( CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(
Fun &&fun, Args &&... args) Fun &&fun, Args &&...args)
{ {
return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke( return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(
std::forward<Fun>(fun), std::forward<Args>(args)...); std::forward<Fun>(fun), std::forward<Args>(args)...);
@@ -7683,7 +7687,7 @@ private:
}; };
struct do_nothing { struct do_nothing {
void operator()() const {} void operator()() const { }
}; };
template <typename T> template <typename T>
@@ -7802,7 +7806,7 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
template <typename Clock, typename Fun, typename... Args> template <typename Clock, typename Fun, typename... Args>
TimingOf<Clock, Fun(Args...)> measure(Fun &&fun, Args &&... args) TimingOf<Clock, Fun(Args...)> measure(Fun &&fun, Args &&...args)
{ {
auto start = Clock::now(); auto start = Clock::now();
auto &&r = Detail::complete_invoke(fun, std::forward<Args>(args)...); auto &&r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
@@ -8153,8 +8157,7 @@ EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(
volatile auto ignored = Clock::now(); volatile auto ignored = Clock::now();
(void)ignored; (void)ignored;
} }
}) }).elapsed;
.elapsed;
}; };
time_clock(1); time_clock(1);
int iters = clock_cost_estimation_iterations; int iters = clock_cost_estimation_iterations;
@@ -8442,7 +8445,7 @@ template <typename T, bool Destruct> struct ObjectStorage {
~ObjectStorage() { destruct_on_exit<T>(); } ~ObjectStorage() { destruct_on_exit<T>(); }
template <typename... Args> void construct(Args &&... args) template <typename... Args> void construct(Args &&...args)
{ {
new (&data) T(std::forward<Args>(args)...); new (&data) T(std::forward<Args>(args)...);
} }
@@ -10082,7 +10085,7 @@ public:
return m_tokenBuffer.front(); return m_tokenBuffer.front();
} }
auto operator-> () const -> Token const * auto operator->() const -> Token const *
{ {
assert(!m_tokenBuffer.empty()); assert(!m_tokenBuffer.empty());
return &m_tokenBuffer.front(); return &m_tokenBuffer.front();
@@ -11380,7 +11383,7 @@ struct IColourImpl {
}; };
struct NoColourImpl : IColourImpl { struct NoColourImpl : IColourImpl {
void use(Colour::Code) override {} void use(Colour::Code) override { }
static IColourImpl *instance() static IColourImpl *instance()
{ {
@@ -11868,7 +11871,8 @@ void formatReconstructedExpression(std::ostream &os, std::string const &lhs,
namespace Catch { namespace Catch {
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && \ #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && \
!defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
[[noreturn]] void throw_exception(std::exception const &e) { [[noreturn]] void throw_exception(std::exception const &e)
{
Catch::cerr() Catch::cerr()
<< "Catch will terminate because it needed to throw an exception.\n" << "Catch will terminate because it needed to throw an exception.\n"
<< "The message was: " << e.what() << '\n'; << "The message was: " << e.what() << '\n';
@@ -11881,8 +11885,10 @@ namespace Catch {
throw_exception(std::logic_error(msg)); throw_exception(std::logic_error(msg));
} }
[[noreturn]] void throw_domain_error( [[noreturn]] void throw_domain_error(std::string const &msg)
std::string const &msg) { throw_exception(std::domain_error(msg)); } {
throw_exception(std::domain_error(msg));
}
[[noreturn]] void throw_runtime_error(std::string const &msg) [[noreturn]] void throw_runtime_error(std::string const &msg)
{ {
@@ -11925,7 +11931,7 @@ std::vector<StringRef> parseEnums(StringRef enums);
namespace Catch { namespace Catch {
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() { }
namespace Detail { namespace Detail {
@@ -11954,7 +11960,7 @@ std::vector<StringRef> parseEnums(StringRef enums)
return parsed; return parsed;
} }
EnumInfo::~EnumInfo() {} EnumInfo::~EnumInfo() { }
StringRef EnumInfo::lookup(int value) const StringRef EnumInfo::lookup(int value) const
{ {
@@ -12033,7 +12039,7 @@ private:
namespace Catch { namespace Catch {
ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {} ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { }
void ExceptionTranslatorRegistry::registerTranslator( void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator *translator) const IExceptionTranslator *translator)
@@ -12278,7 +12284,7 @@ char FatalConditionHandler::altStackMem[sigStackSize] = {};
#else #else
namespace Catch { namespace Catch {
void FatalConditionHandler::reset() {} void FatalConditionHandler::reset() { }
} }
#endif // signals/SEH handling #endif // signals/SEH handling
@@ -12294,13 +12300,13 @@ void FatalConditionHandler::reset() {}
namespace Catch { namespace Catch {
IGeneratorTracker::~IGeneratorTracker() {} IGeneratorTracker::~IGeneratorTracker() { }
const char *GeneratorException::what() const noexcept { return m_msg; } const char *GeneratorException::what() const noexcept { return m_msg; }
namespace Generators { namespace Generators {
GeneratorUntypedBase::~GeneratorUntypedBase() {} GeneratorUntypedBase::~GeneratorUntypedBase() { }
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) auto acquireGeneratorTracker(SourceLineInfo const &lineInfo)
-> IGeneratorTracker & -> IGeneratorTracker &
@@ -12496,7 +12502,7 @@ TestRunStats::TestRunStats(
TestRunStats::~TestRunStats() = default; TestRunStats::~TestRunStats() = default;
void IStreamingReporter::fatalErrorEncountered(StringRef) {} void IStreamingReporter::fatalErrorEncountered(StringRef) { }
bool IStreamingReporter::isMulti() const { return false; } bool IStreamingReporter::isMulti() const { return false; }
IReporterFactory::~IReporterFactory() = default; IReporterFactory::~IReporterFactory() = default;
@@ -12539,7 +12545,7 @@ LeakDetector::LeakDetector()
#else #else
Catch::LeakDetector::LeakDetector() {} Catch::LeakDetector::LeakDetector() { }
#endif #endif
@@ -14145,7 +14151,7 @@ struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
m_generator = std::move(generator); m_generator = std::move(generator);
} }
}; };
GeneratorTracker::~GeneratorTracker() {} GeneratorTracker::~GeneratorTracker() { }
} }
RunContext::RunContext( RunContext::RunContext(
@@ -15056,8 +15062,8 @@ int Session::runInternal()
// the return value to 255 prevents false negative when some multiple // the return value to 255 prevents false negative when some multiple
// of 256 tests has failed // of 256 tests has failed
return (std::min)(MaxExitCode, return (std::min)(MaxExitCode,
(std::max)( (std::max)(totals.error,
totals.error, static_cast<int>(totals.assertions.failed))); static_cast<int>(totals.assertions.failed)));
} }
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
catch (std::exception &ex) catch (std::exception &ex)
@@ -15086,7 +15092,7 @@ static auto getSingletons() -> std::vector<ISingleton *> *&
} }
} }
ISingleton::~ISingleton() {} ISingleton::~ISingleton() { }
void addSingleton(ISingleton *singleton) void addSingleton(ISingleton *singleton)
{ {
@@ -15519,7 +15525,7 @@ RegistrarForTagAliases::RegistrarForTagAliases(
namespace Catch { namespace Catch {
TagAliasRegistry::~TagAliasRegistry() {} TagAliasRegistry::~TagAliasRegistry() { }
TagAlias const *TagAliasRegistry::find(std::string const &alias) const TagAlias const *TagAliasRegistry::find(std::string const &alias) const
{ {
@@ -15562,7 +15568,7 @@ void TagAliasRegistry::add(std::string const &alias, std::string const &tag,
<< "\tRedefined at: " << lineInfo); << "\tRedefined at: " << lineInfo);
} }
ITagAliasRegistry::~ITagAliasRegistry() {} ITagAliasRegistry::~ITagAliasRegistry() { }
ITagAliasRegistry const &ITagAliasRegistry::get() ITagAliasRegistry const &ITagAliasRegistry::get()
{ {
@@ -17428,7 +17434,7 @@ std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities()
return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High}; return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High};
} }
void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} void TestEventListenerBase::assertionStarting(AssertionInfo const &) { }
bool TestEventListenerBase::assertionEnded(AssertionStats const &) bool TestEventListenerBase::assertionEnded(AssertionStats const &)
{ {
@@ -17702,7 +17708,7 @@ void CompactReporter::noMatchingTestCases(std::string const &spec)
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
void CompactReporter::assertionStarting(AssertionInfo const &) {} void CompactReporter::assertionStarting(AssertionInfo const &) { }
bool CompactReporter::assertionEnded(AssertionStats const &_assertionStats) bool CompactReporter::assertionEnded(AssertionStats const &_assertionStats)
{ {
@@ -17739,7 +17745,7 @@ void CompactReporter::testRunEnded(TestRunStats const &_testRunStats)
StreamingReporterBase::testRunEnded(_testRunStats); StreamingReporterBase::testRunEnded(_testRunStats);
} }
CompactReporter::~CompactReporter() {} CompactReporter::~CompactReporter() { }
CATCH_REGISTER_REPORTER("compact", CompactReporter) CATCH_REGISTER_REPORTER("compact", CompactReporter)
@@ -18156,7 +18162,7 @@ void ConsoleReporter::reportInvalidArguments(std::string const &arg)
stream << "Invalid Filter: " << arg << std::endl; stream << "Invalid Filter: " << arg << std::endl;
} }
void ConsoleReporter::assertionStarting(AssertionInfo const &) {} void ConsoleReporter::assertionStarting(AssertionInfo const &) { }
bool ConsoleReporter::assertionEnded(AssertionStats const &_assertionStats) bool ConsoleReporter::assertionEnded(AssertionStats const &_assertionStats)
{ {
@@ -18571,7 +18577,7 @@ JunitReporter::JunitReporter(ReporterConfig const &_config)
m_reporterPrefs.shouldReportAllAssertions = true; m_reporterPrefs.shouldReportAllAssertions = true;
} }
JunitReporter::~JunitReporter() {} JunitReporter::~JunitReporter() { }
std::string JunitReporter::getDescription() std::string JunitReporter::getDescription()
{ {
@@ -18579,7 +18585,7 @@ std::string JunitReporter::getDescription()
"junitreport target"; "junitreport target";
} }
void JunitReporter::noMatchingTestCases(std::string const & /*spec*/) {} void JunitReporter::noMatchingTestCases(std::string const & /*spec*/) { }
void JunitReporter::testRunStarting(TestRunInfo const &runInfo) void JunitReporter::testRunStarting(TestRunInfo const &runInfo)
{ {
@@ -19063,7 +19069,7 @@ void XmlReporter::sectionStarting(SectionInfo const &sectionInfo)
} }
} }
void XmlReporter::assertionStarting(AssertionInfo const &) {} void XmlReporter::assertionStarting(AssertionInfo const &) { }
bool XmlReporter::assertionEnded(AssertionStats const &assertionStats) bool XmlReporter::assertionEnded(AssertionStats const &assertionStats)
{ {

View File

@@ -11,12 +11,12 @@ public:
class B : public A { class B : public A {
public: public:
virtual void foo_a() override {} virtual void foo_a() override { }
}; };
class C : public A { class C : public A {
public: public:
virtual void foo_c() override {} virtual void foo_c() override { }
}; };
class D : public B, public C { class D : public B, public C {

View File

@@ -15,9 +15,9 @@ public:
A(const A &) = default; A(const A &) = default;
virtual ~A() = default; virtual ~A() = default;
void basic_method() {} void basic_method() { }
static int static_method() { return 0; } static int static_method() { return 0; }
void const_method() const {} void const_method() const { }
auto auto_method() { return 1; } auto auto_method() { return 1; }
auto double_int(const int i) { return 2 * i; } auto double_int(const int i) { return 2 * i; }
@@ -37,7 +37,7 @@ public:
static const auto auto_member{10UL}; static const auto auto_member{10UL};
protected: protected:
void protected_method() {} void protected_method() { }
int protected_member; int protected_member;
@@ -46,7 +46,7 @@ protected:
}; };
private: private:
void private_method() {} void private_method() { }
int private_member; int private_member;
int a, b, c; int a, b, c;

View File

@@ -3,7 +3,7 @@ namespace t00004 {
class A { class A {
public: public:
void foo() const {} void foo() const { }
class AA { class AA {
public: public:
@@ -13,7 +13,7 @@ public:
}; };
}; };
void foo2() const {} void foo2() const { }
}; };
} }
} }

View File

@@ -14,7 +14,7 @@ template <typename T> class D {
class A { class A {
private: private:
void foo() {} void foo() { }
friend class B; friend class B;
friend class external::C; friend class external::C;
// TODO // TODO

View File

@@ -27,7 +27,7 @@ class R;
struct D { struct D {
int d; int d;
void print(R *r) {} void print(R *r) { }
}; };
template <typename T> struct E { template <typename T> struct E {

View File

@@ -8,7 +8,8 @@ class A {
} }
namespace ns2_v0_9_0 { namespace ns2_v0_9_0 {
class [[deprecated]] A {}; class [[deprecated]] A {
};
} }
namespace { namespace {

View File

@@ -15,20 +15,20 @@ public:
class Visitor1 : public Visitor { class Visitor1 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Visitor2 : public Visitor { class Visitor2 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Visitor3 : public Visitor { class Visitor3 : public Visitor {
public: public:
void visit_A(const A &item) const override {} void visit_A(const A &item) const override { }
void visit_B(const B &item) const override {} void visit_B(const B &item) const override { }
}; };
class Item { class Item {
@@ -39,12 +39,12 @@ public:
class A : public Item { class A : public Item {
public: public:
void accept(const Visitor &visitor) const override {} void accept(const Visitor &visitor) const override { }
}; };
class B : public Item { class B : public Item {
public: public:
void accept(const Visitor &visitor) const override {} void accept(const Visitor &visitor) const override { }
}; };
} }
} }

View File

@@ -18,14 +18,14 @@ protected:
class A1 : public A { class A1 : public A {
protected: protected:
void method1() override {} void method1() override { }
void method2() override {} void method2() override { }
}; };
class A2 : public A { class A2 : public A {
protected: protected:
void method1() override {} void method1() override { }
void method2() override {} void method2() override { }
}; };
} }
} }

View File

@@ -11,17 +11,17 @@ public:
class StrategyA : public Strategy { class StrategyA : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class StrategyB : public Strategy { class StrategyB : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class StrategyC : public Strategy { class StrategyC : public Strategy {
public: public:
void algorithm() override {} void algorithm() override { }
}; };
class Context { class Context {

View File

@@ -13,14 +13,14 @@ public:
class Target1 : public Target { class Target1 : public Target {
public: public:
void m1() override {} void m1() override { }
void m2() override {} void m2() override { }
}; };
class Target2 : public Target { class Target2 : public Target {
public: public:
void m1() override {} void m1() override { }
void m2() override {} void m2() override { }
}; };
class Proxy : public Target { class Proxy : public Target {

View File

@@ -5,14 +5,14 @@ namespace t00025 {
class Target1 { class Target1 {
public: public:
void m1() {} void m1() { }
void m2() {} void m2() { }
}; };
class Target2 { class Target2 {
public: public:
void m1() {} void m1() { }
void m2() {} void m2() { }
}; };
template <typename T> class Proxy { template <typename T> class Proxy {

View File

@@ -16,7 +16,7 @@ class Line : public Shape, public T<Line<>>... {
public: public:
void display() override void display() override
{ {
std::apply([](auto &&... x) { (x.display(), ...); }, std::apply([](auto &&...x) { (x.display(), ...); },
std::forward_as_tuple(T<Line<>>()...)); std::forward_as_tuple(T<Line<>>()...));
} }
}; };
@@ -26,7 +26,7 @@ class Text : public Shape, public T<Text<>>... {
public: public:
void display() override void display() override
{ {
std::apply([](auto &&... x) { (x.display(), ...); }, std::apply([](auto &&...x) { (x.display(), ...); },
std::forward_as_tuple(T<Text<>>()...)); std::forward_as_tuple(T<Text<>>()...));
} }
}; };
@@ -37,12 +37,12 @@ struct ShapeDecorator {
template <typename T> class Color : public ShapeDecorator { template <typename T> class Color : public ShapeDecorator {
public: public:
void display() override {} void display() override { }
}; };
template <typename T> class Weight : public ShapeDecorator { template <typename T> class Weight : public ShapeDecorator {
public: public:
void display() override {} void display() override { }
}; };
struct Window { struct Window {

12
tests/t00032/.clang-uml Normal file
View File

@@ -0,0 +1,12 @@
compilation_database_dir: ..
output_directory: puml
diagrams:
t00032_class:
type: class
glob:
- ../../tests/t00032/t00032.cc
using_namespace:
- clanguml::t00032
include:
namespaces:
- clanguml::t00032

38
tests/t00032/t00032.cc Normal file
View File

@@ -0,0 +1,38 @@
#include <memory>
#include <vector>
namespace clanguml {
namespace t00032 {
struct Base {
};
struct TBase {
};
struct A {
void operator()() { }
};
struct B {
void operator()() { }
};
struct C {
void operator()() { }
};
template <typename T, typename L, typename... Ts>
struct Overload : public Base, public T, public Ts... {
using Ts::operator()...;
L counter;
};
template <class... Ts> Overload(Ts...) -> Overload<Ts...>;
struct R {
Overload<TBase, int, A, B, C> overload;
};
} // namespace t00032
} // namespace clanguml

63
tests/t00032/test_case.h Normal file
View File

@@ -0,0 +1,63 @@
/**
* tests/t00032/test_case.cc
*
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
TEST_CASE("t00032", "[test-case][class]")
{
auto [config, db] = load_config("t00032");
auto diagram = config.diagrams["t00032_class"];
REQUIRE(diagram->name == "t00032_class");
REQUIRE(diagram->include.namespaces.size() == 1);
REQUIRE_THAT(diagram->include.namespaces,
VectorContains(std::string{"clanguml::t00032"}));
REQUIRE(diagram->exclude.namespaces.size() == 0);
REQUIRE(diagram->should_include("clanguml::t00032::A"));
auto model = generate_class_diagram(db, diagram);
REQUIRE(model.name == "t00032_class");
auto puml = generate_class_puml(diagram, model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
REQUIRE_THAT(puml, IsClass(_A("Base")));
REQUIRE_THAT(puml, IsClass(_A("TBase")));
REQUIRE_THAT(puml, IsClass(_A("A")));
REQUIRE_THAT(puml, IsClass(_A("B")));
REQUIRE_THAT(puml, IsClass(_A("C")));
REQUIRE_THAT(puml, IsClass(_A("R")));
REQUIRE_THAT(puml, IsClassTemplate("Overload", "T,L,Ts..."));
REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Overload<T,L,Ts...>")));
REQUIRE_THAT(
puml, IsBaseClass(_A("TBase"), _A("Overload<TBase,int,A,B,C>")));
REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("Overload<TBase,int,A,B,C>")));
REQUIRE_THAT(puml, IsBaseClass(_A("B"), _A("Overload<TBase,int,A,B,C>")));
REQUIRE_THAT(puml, IsBaseClass(_A("C"), _A("Overload<TBase,int,A,B,C>")));
save_puml(
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);
}

View File

@@ -13,7 +13,7 @@ struct C {
class A { class A {
public: public:
A() {} A() { }
int add(int x, int y) { return m_c.add(x, y); } int add(int x, int y) { return m_c.add(x, y); }
@@ -28,7 +28,7 @@ public:
return res; return res;
} }
void log_result(int r) {} void log_result(int r) { }
private: private:
detail::C m_c{}; detail::C m_c{};

View File

@@ -135,6 +135,7 @@ using namespace clanguml::test::matchers;
#include "t00029/test_case.h" #include "t00029/test_case.h"
#include "t00030/test_case.h" #include "t00030/test_case.h"
#include "t00031/test_case.h" #include "t00031/test_case.h"
#include "t00032/test_case.h"
// //
// Sequence diagram tests // Sequence diagram tests

View File

@@ -90,6 +90,9 @@ test_cases:
- name: t00031 - name: t00031
title: PlantUML style decorator test case title: PlantUML style decorator test case
description: description:
- name: t00032
title: Class template with template base classes test case
description:
Sequence diagrams: Sequence diagrams:
- name: t20001 - name: t20001
title: Basic sequence diagram title: Basic sequence diagram