How does this default template struct assignment work? [duplicate] - c++

This question already has answers here:
Arrow operator (->) in function heading
(3 answers)
Closed 4 months ago.
I have been digging into some embedded C++ firmware used by DaveJone's (eevblog) uSupply project
https://gitlab.com/eevblog/usupply-firmware.
There is common pattern of code that I just can't quite wrap my head around what is happening.
For example:
In the file "RegistersRCC.hpp" there is a template struct:
template <std::size_t A>
struct CR : public General::u32_reg<A>
{
using base_t = General::u32_reg<A>;
using base_t::base_t;
//PLL register bits
auto PLLRDY () { return base_t::template Actual<RCC_CR_PLLRDY>(); }
auto PLLON () { return base_t::template Actual<RCC_CR_PLLON>(); }
//PLL Management functions
void EnablePLL() noexcept
{
if ( not PLLON().Get() )
{
PLLON() = true;
while ( not PLLRDY().Get() );
}
}
void DisablePLL() noexcept
{
if ( PLLON().Get() )
{
PLLON() = false;
while ( PLLRDY().Get() );
}
}
//Enable clock security
auto CSSON () { return base_t::template Actual<RCC_CR_CSSON>(); }
//High speed external oscillator bits
auto HSEBYP () { return base_t::template Actual<RCC_CR_HSEBYP>(); }
auto HSERDY () { return base_t::template Actual<RCC_CR_HSERDY>(); }
auto HSEON () { return base_t::template Actual<RCC_CR_HSEON>(); }
//HSE Management functions
void EnableHSE()
{
if ( not HSEON().Get() )
{
HSEON() = true; //Enable the clock
while( not HSERDY().Get() ); //Wait for it to stable
}
}
void DisableHSE()
{
if ( HSEON().Get() )
{
HSEON() = false; //Disable the clock
while( HSERDY().Get() ); //Wait for it to disable
}
}
void ConnectHSE()
{
HSEBYP() = false; //Connect it to system
}
void BypassHSE()
{
HSEBYP() = true; //Disconnect it to system
}
//High speed internal oscillator bits
auto HSICAL () { return base_t::template Actual<RCC_CR_HSICAL>(); }
auto HSITRIM() { return base_t::template Actual<RCC_CR_HSITRIM>(); }
auto HSIRDY () { return base_t::template Actual<RCC_CR_HSIRDY>(); }
auto HSION () { return base_t::template Actual<RCC_CR_HSION>(); }
//HSI Management functions, No calibration provided
// these chips are factory calibrated
void EnableHSI()
{
if (not HSION().Get())
{
HSION() = true;
while (!HSIRDY());
}
}
void DisableHSI()
{
if ( HSION().Get() )
{
HSION() = false;
while (HSIRDY());
}
}
};
This struct exists in the namespace:
namespace Peripherals::RCCGeneral
{
}
Within the same namespace/header file there is this "Default"
CR() -> CR<RCC_BASE + offsetof(RCC_TypeDef, CR)>;
I think this is where my gap in understanding lies. What is happening here? Specifically with the lvalue and arrow operator, and why this is located within the header.
Within the files that utilize the RCCRegisters you see usages like:
CR{}.DisablePLL();

This is called class template argument deduction(CTAD) which allows writing deduction guides to the compiler about how to deduce the template arguments from constructor calls.
It is a handy C++17 addition that saves on typing:
std::vector x{1.,2.,3.} //deduces std::vector<double>
C++14 and older requires to explicitly write std::vector<double> which gets tedious and too verbose for some more complex examples.
In this case, the guide
CR() -> CR<RCC_BASE + offsetof(RCC_TypeDef, CR)>;
specifies that the default constructor should deduce A template parameter to RCC_BASE + offsetof(RCC_TypeDef, CR).
The same could have been achieved by simply using a default template argument:
template <std::size_t A = default_value>
struct CR : public General::u32_reg<A>{ ... };
But here comes the catch, offsetof(RCC_TypeDef, CR) is not valid here because at this line, CR doesn't exist yet.
So my assumption is this a fix around this limitation to allow making the default value depend on the class definition itself, quite clever I think.

Related

Can clang-tidy filter to only work within a given namespace?

I'm attempting to refactor my code using clang-tidy and it flags a number of changes that should not be applied. For example, I've defined for my cpp files the format:
{ key: readability-identifier-naming.FunctionCase, value: camelBack }
But it flags fixes for functions outside my control like
static void from_json(const nlohmann::json& aJson,...)
Everything I'm working with is contained within a namespace, so is it possible to only apply readability-identifier-naming to content within a namespace? Can this be done with existing functions or will I need to define my own format checker in the clang-tools-extra?
Update
I solved the issue by modifying IdentifierNamingCheck::getDeclFailureInfo and adding a namespace filter to the FileStyle. I pulled some code from another place. It's not a general solution but it works in my case.
// ...
if (!FileStyle.namespaceFilter().empty()) {
auto testNamespace = [&FileStyle](const DeclContext *DC) {
if (!DC->isNamespace())
return false;
const auto *ND = cast<NamespaceDecl>(DC);
if (ND->isInline()) {
return false;
}
if (!DC->getParent()->getRedeclContext()->isTranslationUnit())
return false;
const IdentifierInfo *II = ND->getIdentifier();
return II && II->isStr(FileStyle.namespaceFilter());
};
bool isNamespace = false;
for (const DeclContext *DC = Decl->getDeclContext(); DC;
DC = DC->getParent()) {
isNamespace |= testNamespace(DC);
if (isNamespace)
break;
}
if (!isNamespace)
return llvm::None;
}
// ...

C++ automatic finalization or objects destruction

In this example I faced the problem of copying the code:
void BadExample1() {
if (!Initialize1())
return;
if (!Initialize2()) {
Finalize1();
return;
}
if (!Initialize3()) {
Finalize1();
Finalize2();
return;
}
if (!Initialize4()) {
Finalize1();
Finalize2();
Finalize3();
return;
}
// some code..
Finalize1();
Finalize2();
Finalize3();
Finalize4();
}
Bnd here is a bad code structure. If I have a lot of constructs, the width of the code will be too large, this is also bad:
void BadExample2() {
if (Initialize1()) {
if (Initialize2()) {
if (Initialize3()) {
if (Initialize4()) {
if (Initialize5()) {
// some code..
Finalize5();
}
Finalize4();
}
Finalize3();
}
Finalize2();
}
Finalize1();
}
}
How can I save good code sturcture and solve code copying?
Finalize1/2/3 is a API functions and not my program classes.
Maybe some STL containers can solve it?
Maybe something like that?
void GoodExample() {
if (!Initialize1())
return;
RaiiWrapper<void(*)()> raii_wrapper1([]() {
Finalize1();
});
if (!Initialize2()) {
//Finalize1();
return;
}
RaiiWrapper<void(*)()> raii_wrapper2([]() {
Finalize2();
});
if (!Initialize3()) {
//Finalize1();
//Finalize2();
return;
}
RaiiWrapper<void(*)()> raii_wrapper3([]() {
Finalize3();
});
if (!Initialize4()) {
//Finalize1();
//Finalize2();
//Finalize3();
return;
}
RaiiWrapper<void(*)()> raii_wrapper4([]() {
Finalize4();
});
// some code..
//Finalize1();
//Finalize2();
//Finalize3();
//Finalize4();
}
Why not use real objects?
struct SetupPart1 {
SetupPart1 () { if (!Initialize1() throw std::runtime_error("Part1"); }
~SetupPart1 () { Finalize1(); }
};
and so on for part 2, 3, 4, etc.
Now your example looks like this:
void GoodExample() {
try {
SetupPart1 p1;
SetupPart2 p2;
SetupPart3 p3;
SetupPart4 p4;
// some code ...
}
catch { const std::runtime_error &ex ) {
std::cerr << "GoodExample Failed: " << ex.what << std::end;
}
}
You could streamline Marshall's suggestion and use the not-yet-standardized std::make_unique_resource() (this function is closely related to scope_guard, a contraption suggested by Andrei Alexandrescu some years ago and also in that proposal). That gives you an object with two functions - one to run at the variable scope's start, another to run at its end (i.e. on construction and destruction respectively).
Then, instead of defining four separate classes, you'd just write:
void GoodExample() {
auto r1 = std::make_unique_resource(Initialize1, Finalize1);
auto r2 = std::make_unique_resource(Initialize2, Finalize2);
auto r3 = std::make_unique_resource(Initialize3, Finalize3);
auto r4 = std::make_unique_resource(Initialize4, Finalize4);
// some code
}
The proposal has code for the implementation; and - it's not complex at all. So you could just copy the implementation and create your own not_std::make_unique_resource() function and related templated class(es).
Whenever you get a precious resource from an API, you need to wrap it as an object with the appropriate destructor. So, if Initialize1 initialises something1 then something1 should really be an object Something1 that knows how to initialise and how to finalise itself. Also, a failure to initialise should throw an exception (this is not done with fstream because fstream is older than this concept).
class Something1 {
public: Something1 () { if (!Initialize1()) throw resource_failed ("1"); }
~Something1 () { Finalize1(); }
}

Function returning a container containing specific elements of input container

I have a vector or list of which I only want to apply code to specific elements. E.g.
class Container : public std::vector<Element*>
Or
class Container : public std::list<Element*>
And:
Container newContainer = inputContainer.Get(IsSomething);
if (!newContainer.empty()) {
for (Element* const el: newContainer ) {
[some stuff]
}
} else {
for (Element* const el : inputContainer) {
[some stuff]
}
}
I've written a member function Get() as follows.
template<typename Fn>
auto Container::Get(const Fn& fn) const {
Container output;
std::copy_if(cbegin(), cend(), std::inserter(output, output.end()), fn);
return output;
}
and IsSomething would be a lambda, e.g.
auto IsSomething= [](Element const* const el)->bool { return el->someBool; };
From performance perspective: Is this a good approach? Or would it be better to copy and remove?
template<typename Fn>
auto Container::Get(const Fn& fn) const {
Container output(*this);
output.erase(std::remove_if(output.begin(), output.end(), fn), end(output));
return output;
}
Or is there a better approach anyhow?
edit: different example
As my previous example can be written in a better way, let's show a different example:
while (!(container2 = container1.Get(IsSomething)).empty()&&TimesFooCalled<SomeValue)
{
Container container3(container2.Get(IsSomething));
if (!container3.empty()) {
Foo(*container3.BestElement());
} else {
Foo(*container2.BestElement());
}
}
Not answering your direct question, but note that you can implement the original algorithm without copying anything. Something like this:
bool found = false;
for (Element* const el: inputContainer) {
if (IsSomething(el)) {
found = true;
[some stuff]
}
}
if (!found) {
for (Element* const el : inputContainer) {
[some stuff]
}
}
The usual pattern that I use is something like this:
for(auto const * item : inputContainer) if(IsSomething(item)) {
// Do stuff with item
}
This is usually good enough, so other approaches seem overkill.
For better performance it is always better not to copy or remove elements from the list you get. In my experience it's even faster if you only go through the list once, for caching reasons. So here is what I would do to find one or the other "best" value from a list:
auto const isBetter = std::greater<Element>();
Element const * best = nullptr, const * alt_best = nullptr;
for(Element const * current : inputContainer) {
if(IsSomething(current)) {
if(!best || isBetter(*best, *current)) best = current;
} else {
if(!alt_best || isBetter(*alt_best, *current)) alt_best = current;
}
}
if(best) {
// do something with best
} else if(alt_best) {
// do something with alt_best
} else {
// empty list
}
If you find yourself doing this a lot or you want to make this part of your class's interface you could consider writing an iterator that skips elements you don't like.
If you actually want to remove the item from the list, you could do something like this:
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer),
[](Element const *item) {
if(IsSomething(item)) {
// Do something with item
return true;
}
return false;
}
));

Nested Matchers in GTest

I would like to use some existing matchers in other matcher. I know about the MatcherInterface solution but I was wondering can I use matchers which were defined by MATCHER_P. If found this solution:
struct Foo
{
double x;
double y;
};
struct Bar
{
Foo foo;
int i;
};
MATCHER_P(EqFoo, foo, "")
{
::testing::Matcher<double> x_matcher = ::testing::DoubleNear(foo.x, 0.0001);
if (!x_matcher.MatchAndExplain(arg.x, result_listener))
{
return false;
}
::testing::Matcher<double> y_matcher = ::testing::DoubleNear(foo.y, 0.0001);
if (!y_matcher.MatchAndExplain(arg.y, result_listener))
{
return false;
}
return true;
}
MATCHER_P(EqBar, bar, "")
{
::testing::Matcher<Foo> foo_matcher = EqFooMatcherP<Foo>(bar.foo);
if (!foo_matcher.MatchAndExplain(arg.foo, result_listener))
{
return false;
}
if (bar.i != arg.i)
{
return false;
}
return true;
}
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, EqBar(bar_exp));
}
I am just wondering, is there any better and nicer solution to
use my own MATCHER_P matcher in another one
use an original GTest matcher in another one.
The correct way is to use, as much as possible, the matchers from gtest/gmock. Only if there is no already provided matchers - use your own.
In your example - it is just as simple as this:
auto EqFoo(const Foo& expected)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, ::testing::DoubleNear(expected.x, 0.0001)),
::testing::Field(&Foo::y, ::testing::DoubleNear(expected.y, 0.0001))
);
}
auto EqBar(const Bar& expected)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, EqFoo(expected.foo)),
::testing::Field(&Bar::i, expected.i)
);
}
More general approach is to use overloads:
auto MatchDouble(double expected)
{
return ::testing::DoubleNear(expected.x, 0.0001);
}
auto MatchFoo(::testing::Matcher<double> x, ::testing::Matcher<double> y)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, x),
::testing::Field(&Foo::y, y)
);
}
auto MatchFoo(double x, double y)
{
return MatchFoo(MatchDouble(x), MatchDouble(y));
}
auto MatchBar(::testing::Matcher<Foo> foo, ::testing::Matcher<int> i)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, foo),
::testing::Field(&Bar::i, expected.i),
);
}
auto MatchBar(const Bar& expected)
{
return MatchBar(expected.foo, expected.i);
}
So your test:
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, MatchBar(bar_exp));
// or - e.g. you can match only Bar::y if other things are irrelevant in your test
EXPECT_THAT(bar_val, MatchBar(MatchFoo(_, MatchDouble(2.001)), _);
}
Anyway - using MATCHER_P should be rather rare case, my own observation is that this macro is really overused.
In case your project is pre-C++14 - use ::testing::Matcher<T> instead of auto as return type for all of these functions.

constructor not getting called?

Ive been staring at my code and I can't figure out why on earth my constructor is not gettign called.
It's just ignoring my constructor completely (i've check with stepping with debugger).
Here's my testapp:
using namespace MyEngine;
int _tmain(int argc, _TCHAR* argv[])
{
TestManager* testMgr = new TestManager();
testMgr->RunAllTests();
delete testMgr;
getchar();
return 0;
}
TestManager.h:
namespace MyEngine
{
class TestManager
{
public:
TestManager();
TestManager(uint64_t RepeatTimes);
~TestManager();
bool RunAllTests();
bool RunMemoryTests();
private:
Engine* mEngine;
ILogManager* mLogger;
MemoryTestManager* mMemTestMgr;
uint64_t mRepeatTimes;
};
}
and TestManager.cpp
namespace MyEngine
{
TestManager::TestManager()
{
TestManager(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
TestManager::~TestManager()
{
}
/* Runs all testing modules */
bool TestManager::RunAllTests()
{
bool res = true;
/* Init Engine */
if(mEngine->Init(0,0,0))
{
res = true;
res && mEngine->GetRenderManager()->Init();
res && mLogger->Init(true,true);
res && mEngine->GetMemoryManager()->Init(false);
}
else
return false;
/* Start Engine */
mEngine->Start();
/* Get logger */
mLogger = mEngine->GetLogger();
/* Run Memory Tests */
res &= RunMemoryTests();
if (res)
mLogger->LogInfo("TEST: TESTING SUCCESSFULL");
else
mLogger->LogError("TEST: TESTING FAILED");
return res;
}
/* Runs all memory tests */
bool TestManager::RunMemoryTests()
{
bool res = true;
res &= mMemTestMgr->AllocateTest();
res &= mMemTestMgr->ReferenceTest();
if (res)
mLogger->LogInfo("TEST: RunMemoryTests SUCCESSFULL");
else
mLogger->LogError("TEST: RunMemoryTests FAILED");
return res;
}
}
You cant call another constructor from the same class. I'd refactor the init code into a separate method and call it from both constructors:
namespace MyEngine
{
TestManager::TestManager()
{
Init(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
Init(RepeatTimes);
}
void TestManager::Init(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
}
When you call TestManager(1); inside your TestManager::TestManager() constructor, you're creating another instance of TestManager, using the constructor TestManager::TestManager(uint64_t).
You can't do this on C++, you have to create either a init method, were you set the instance variables to whatever you want, or use optional parameters:
TestManager(uint64_t RepeatTimes = 0);
Then, if you create an instance of TestManager without arguments, you will be calling the TestManager::TestManager(uint64_t)constructor with 0 as the uint64_t argument.
you can't call a default constructor from a overloaded constructor. Why don't you simply create you object like this:
TestManager* testMgr = new TestManager(1);
Using a default argument (as per fontanini's answer) will do what you want in this case.
But if this is a simplified example and you really do want to delegate to another constructor, then that's not possible in C++03 - the line TestManager(1) just constructs a temporary object which goes unused (and the line will probably be optimized out unless the TestManager(uint64_t) constructor has side effects).
However, you can do what you're aiming for here with a C++11 compiler and the following syntax:
TestManager::TestManager() :
TestManager(1)
{
}