Let's say I'm developing a logging functionality. Inside logging.h I declare the function to be used by the application later on.
// logging.h
#include <string>
namespace logging {
void LogThis(const std::string& text);
}; // namespace logging
Its definition is obviously inside logging.cpp:
// logging.cpp
void logging::LogThis(const std::string& text) {
std::cout << "Log: " << text << '\n';
}
Now lets pretent that my LogThis function's work is split up into some smaller helper functions. They're not part of the logging interface. Let's take a Prettify function as an example.
// logging.cpp
void logging::LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
My question is: Where do I put the function declaration of Prettify? I shouldn't include it in the logging.h header file, because then it can be called by other compilation units and its not part of the interface. So just put it inside logging.cpp instead like this?
// logging.cpp
namespace logging {
void Prettify(std::string& ugly_text);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
void Prettify(std::string& ugly_text) {
// making it pretty...
}
}
I'm looking for some best practices / rules of thumb / opinions on this :) Thanks in advance!
For things that are only needed within the file, I would just place it in an anonymous namespace within the C++ file itself, sort of the modern equivalent of the legacy C static keyword on functions(a):
namespace {
void WeaveMagic(std::string& ugly_text) {
WeaveMoreMagic(ugly_text);
}
void Prettify(std::string& ugly_text) {
WeaveMagic(ugly_text);
}
}
If you place this before any use of the functions, and ensure a strict hierarchy of calls, you can skip the declarations since the definitions provides the required information, as shown above.
Of course, if there are any circular dependencies between multiple anonymous functions (i.e., circular recursion), you will still need to provide declarations:
#include <iostream>
namespace {
int DivThree(int val); // needed to implement AddOne()
int AddOne(int val) {
std::cout << "AddOne " << val << " -> " << (val + 1) << '\n';
if (val > 0) return DivThree(val + 1);
return val;
}
int DivThree(int val) {
std::cout << "DivThree " << val << " -> " << (val / 3) << '\n';
return AddOne(val / 3);
}
}
int main(){
int final = AddOne(18);
std::cout << "Final " << final << '\n';
return 0;
}
And, yes, that's very contrived, but good examples of circular recursion are few and far between :-) The output is:
AddOne 18 -> 19
DivThree 19 -> 6
AddOne 6 -> 7
DivThree 7 -> 2
AddOne 2 -> 3
DivThree 3 -> 1
AddOne 1 -> 2
DivThree 2 -> 0
AddOne 0 -> 1
Final 0
(a) CPP Core Guidline SF.22 actually covers this:
Use an unnamed (anonymous) namespace for all internal/non-exported entities.
Reason: Nothing external can depend on an entity in a nested unnamed namespace. Consider putting every definition in an implementation source file in an unnamed namespace unless that is defining an "external/exported" entity.
An API class and its members can't live in an unnamed namespace; but any "helper" class or function that is defined in an implementation source file should be at an unnamed namespace scope.
If you are operating on functions only, as #paxdiablo have written, you can use anonymous namespace (look at his answer).
I have some C-based habits, so personally I would also see it as static function. But I'm not sure how C++ fanatics will look at it :). static (in this context) makes functions local for compilation unit (logging.cpp), so it cannot be linked from outside.
//logging.cpp
static void Prettify(std::string& ugly);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
static void Prettify(std::string& ugly) { }
However if your logging utility would be object-oriented. I suggest you to use D-pointer and Q-Pointer design pattern (known also as PImpl idiom) - https://en.cppreference.com/w/cpp/language/pimpl .
//logging.h
#include <string>
class loggingImpl;
class logging {
public :
logging();
virtual ~logging();
void LogThis(const std::string& text);
protected :
loggingImpl *impl;
};
//logging.cpp
class loggingImpl
{
public :
loggingImpl(logging *p) : qptr(p) { }
void Prettify(std::string& ugly) { }
//anything what you need and should be hided
// access parent through qptr
protected :
logging *qptr;
};
logging::logging() : impl(new loggingImpl) { }
logging::~logging() { delete impl; }
void logging::LogThis(const std::string& text) {
impl->Prettify(text);
std::cout << "Log: " << text << '\n';
}
As you have written, putting declaration in header file is not proper due to limiting visibility of unused symbols.
Related
I am attempting to create a wrapper around class functions. The purpose of my wrapper is to test input, output, and enforce order of operations with various calls throughout my program. I am trying to not make any changes to the callee class. Attached is an example of what I am trying to achieve, but unable to figure out.
Main.cpp
#include "func_warpper.h"
#include "func.h"
int main()
{
func_wrapper fw
fun func;
int origValue = 5;
fw.caller([&](int origValue) { func.f(origValue); }, origValue);
int output = func.getResult().number;
std::cout << " value outputed by function 2 : " << output << std::endl;
// output
// note that above line does give me the result I am looking for
// however, I want to be able to get this inside the function of caller
return 0;
}
func.h .... I want this to be unmodified
#ifndef FUN_H
#define FUN_H
class fun
{
public:
struct result
{
int number;
};
fun();
~fun();
void f(int value);
struct result getResult(){return this->testResult;};
private:
struct result testResult;
};
#endif
func.cpp .... I want this to be unmodified
#include "func.h"
fun::fun(){
this->testResult.number = 0;
return;
}
fun::~fun(){
return;
}
void fun::f(int value){
int updateValue = value * 5;
this->testResult.number = updateValue;
}
func_wrapper.h .... I can modify this until the cows come home, please go ham with recommended changes :)
class func_wrapper
{
public:
struct new_result
{
int new_number;
};
func_wrapper();
~func_wrapper();
void caller(std::function<void(int)> clb, int val);
struct new_result getNewResult() { return this->new_testResult; };
private:
struct new_result new_testResult;
};
#endif
func_wrapper.cpp .... same as above, I can modify this until the cows come home, please go ham with recommended changes :)
#include "func_wrapper.h"
func_wrapper::func_wrapper()
{
//ctor
this->new_testResult.new_number = 0;
return;
}
func_wrapper::~func_wrapper()
{
//dtor
}
void func_wrapper::caller(std::function<void(int)> clb, int val)
{
std::cout << " value entered into function: " << val << std::endl;
// clb(val); seems to call the function but does not store locally anything
clb(val);
clb;
// clb; seems to store all the information locally however I seem unable to
// to reach the infromation: clb -> [functor] -> func -> testResult -> number
// would like ...
int output = clb ??? // the result of what gets filled from number struct
// if I attempt to #include func.h
// func func;
// func.getResult().number; locally the answer is zero with or without delay
}
Through several days of searching, I have not found anything that can help with this problem, to include similar enough questions on stack overflow. Any help would be greatly appreciated, thank you.
So, my understanding is that inside func_wrapper::caller you want to be able to access the wrapped class that is inside your callback. Unfortuately, the way you are doing it, is impossible. There is no (legitimate) way to reach inside the function and access its arguments.
However, if you break up the operation into its component parts, you can do what you want. You would want a caller function more like this:
template <typename Type, typename Function>
void caller(Type&& functor, Function function, int val)
{
std::cout << " value entered into function: " << val << std::endl;
std::invoke(function, functor, val);
std::cout << "value inside wrapper: " << functor.getResult().number << "\rn";
}
and then call it like this.
fw.caller(func, &fun::f, origValue);
https://godbolt.org/z/151YfEeoo
#JohnFilleau had mentioned to pass the class object instead of the function from within the class. The following is the solution based on example code that he provided, and I modified to work with the example. I realize the question is confusing but would like to thank both JohnFilleau and Taekahn for the discussion.
In main.cpp
int main()
{
func_wrapper fw;
fun func;
int origValue = 5;
fw.caller2(func, origValue);
return 0:
}
func_wrapper::caller2
void func_wrapper::caller2(fun& fun, int val)
{
std::cout << " value entered into function: " << val << std::endl;
fun.f(val);
int output = fun.getResult().number;
std::cout << " did this work: " << output << std::endl;
}
In the header I had to add
#include "func.h"
with the change to the header as follows
void caller2(fun& fun, int val);
Firstly, there is a question with a similar goal described here: C++ unit test testing, using template test class.
This question is regarding my attempt to solve the same problem.
Using the Microsoft CppUnitTestFramework, we can create unit tests using something like the following:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace MyUnitTests {
TEST_CLASS(NameOfMyTestClass) {
public:
TEST_METHOD(MyMethod1) {
Assert::IsTrue(false);
}
};
}
I'd like to test a collection of similar tests (without using a For loop to put all of the Asserts in a single TEST_METHOD), so I looked at the TEST_CLASS macro:
#define TEST_CLASS(className) \
ONLY_USED_AT_NAMESPACE_SCOPE class className : public ::Microsoft::VisualStudio::CppUnitTestFramework::TestClass<className>
This can't be used with a template directly - as far as I can see there is no way to specify a className value that would include template parameters with the correct syntax to compile.
As a result, I attempted the following:
namespace MyUnitTests {
ONLY_USED_AT_NAMESPACE_SCOPE
template<MyEnumClass MeasurementType, char ExpectedShift>
class templatedScaleTestClass : public TestClass<templatedScaleTestClass<MeasurementType,ExpectedShift>>
{
public:
TEST_METHOD(Test_ExpectedShift) {
Assert::AreEqual(ExpectedShift, Calculations::getShiftAmount(MeasurementType));
}
};
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::FIRST,3>;
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::THIRD,1>;
}
This compiles, and looks to me like it should allow me to define a collection of TEST_METHODs in the template class, then just instantiate the necessary collection of Enums and constant values to set them up (perhaps using some sort of constructor for other parameters in the future, although looking at CppUnitTest.h makes me wonder if that might be another problem...)
However, the class never appears in the test explorer, and trying to right click on the test (in the template code) and clicking "Run Test(s)" produces the following output:
[datetime Informational] Executing test method 'MyUnitTests.templatedScaleTestClass<MeasurementType, ExpectedShift>.Test_ExpectedShift'
[datetime Informational] No tests found to run.
Edit: Not sure how relevant the last part ("No tests found to run") is - doing the same with a normal test (no user-side templates) produces the same output. Clicking away from a specific test runs all tests in the .cpp file. Perhaps I'm using the right-click menu wrongly.
Despite having tried several attempts at getting this to display, and checking the output of a function like the following:
template<typename T>
void debugMethod(TestClass<T> *tc) {
const TestClassInfo* classInfo = tc->__GetTestClassInfo();
std::stringstream msg;
msg << "Tag: " << classInfo->metadata->tag << std::endl;
msg << "helpMethodName: " << classInfo->metadata->helpMethodName << std::endl;
msg << "helpMethodDecoratedName: " << classInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "New method address: " << &(classInfo->pNewMethod) << std::endl;
const MemberMethodInfo* methodInfo = T::__GetTestMethodInfo_Debug();
msg << "methodInfo - Tag: " << methodInfo->metadata->tag << std::endl;
msg << "methodInfo - methodName: " << methodInfo->metadata->methodName << std::endl;
msg << "methodInfo - helpMethodName: " << methodInfo->metadata->helpMethodName << std::endl;
msg << "methodInfo - helpMethodDecoratedName: " << methodInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "methodInfo - lineNo: " << methodInfo->metadata->lineNo << std::endl;
Logger::WriteMessage(msg.str().c_str());
}
... (namespace, test class etc)
TEST_METHOD(Debug) { debugMethod(this); }
and observing similar results in both a standard TEST_CLASS and my templated class, I was unable to get templated classes to display in the Test Explorer.
It is possible to template a class then call the test functions from a non-templated class:
template <MyEnum val>
class myClass : public TestClass<myClass<val>>
{
public:
TEST_METHOD(MyTest) {
Assert::AreEqual(val, MyEnum::exampleValue);
}
}
TEST_CLASS(DummyTests) {
TEST_METHOD(Test_across) {
auto a = myClass<MyEnum::MyEnumValue>();
a.MyTest();
}
}
but this still provides less than ideal feedback in the Test Explorer.
A further alternative (ugly as it is...) is to define a macro function that takes the parameter you want to template on, and then define your entire class inside the macro:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#define SCALING_TEST(TYPE_TO_TEST, EXPECTED_SHIFT)\
TEST_CLASS(CATNAME(ScalingTest_, TYPE_TO_TEST)) {\
private:\
MyEnum type = MyEnum::TYPE_TO_TEST;\
public:\
TEST_METHOD(HasExpectedShift) {\
Assert::AreEqual((char)EXPECTED_SHIFT, Calculations::getShiftAmount(type));\
}\
}
namespace ScalingTests {
SCALING_TEST(SPEED, 3);
}
i have a relatively small c++ project and i decided to make a Utils header file which would just contain some small helper functions etc. It was all working fine when i was declaring functions that were using a template, then i tried to make a function which didnt need a template, and suddently it doesn't work.
The result i get is a linker error; already defined in (file).obj
I cannot even declare a simple void function, everything without template gives a linker error.
I have NO IDEA whatsoever what could be causing this. Here is the code for the header file... Thanks in advance.
#pragma once
namespace Utils
{
std::string GetActiveWindowTitle()
{
// This doesnt work either, also gives linker error.
return active_window;
}
template<typename T>
void Print(char * value, T printValue)
{
std::cout << value << ": " << printValue << std::endl;
}
template<typename T>
void Print(T printValue)
{
std::cout << "DEBUG: " << printValue << std::endl;
}
void PrintStr(std::string str)
{
// This doesn't work because it doesnt have the template, it gives a linker error
std::cout << "DEBUG: " << str.c_str() << std::endl;
}
}
A function-template is implicitly inline. Thus, when defined in a header file, it doesn't violate ODR (One Definition Rule). For non-template functions in header files, you should either define them as inline, or define them in a separate translation unit.
So, you could do:
#pragma once
namespace Utils
{
inline std::string GetActiveWindowTitle()
{
return active_window;
}
template<typename T>
void Print(char * value, T printValue)
{
std::cout << value << ": " << printValue << std::endl;
}
template<typename T>
void Print(T printValue)
{
std::cout << "DEBUG: " << printValue << std::endl;
}
inline void PrintStr(std::string str)
{
std::cout << "DEBUG: " << str.c_str() << std::endl;
}
}
See Inline keyword vs header definition
If you include your header to more than one cpp, the function will be defined more than once and the linker will give you the error described above. See What is the difference between a definition and a declaration? or What are forward declarations in C++?
Is there a non-macro way in C++ of printing a variable name with its value. Here is the macro way:
#define SHOW(a) std::cout << #a << ": " << (a) << std::endl
PS: I'm using Linux and do not need a cross-platform solution
No, C++ does not support reflection and the only way of doing this (as far as I know) are with macros.
You can use dynamic symbols, but then it will only work in shared libraries or executables compiled with the -rdynamic flag. And it will recognize just global variables with default dynamic visibility.
#include <dlfcn.h>
#include <iostream>
int NameMe = 42;
const char *GetName(const void *ptr)
{
Dl_info info;
if (dladdr(ptr, &info))
return info.dli_sname;
else
return NULL;
}
template<typename T>
void Dump(const T &t)
{
const char *name = GetName(&t);
if (name)
std::cout << name;
else
std::cout << "<unknown>";
std::cout << ": " << t << std::endl;
}
int main()
{
int NoName = 33;
Dump(NameMe);
Dump(NoName);
return 0;
}
$ g++ dump.cpp -ldl -rdynamic
$ ./a.out
NameMe: 42
<unknown>: 33
No way.
Without macro, you've to do this:
std::cout <<"a : " << a << std::endl;
No other way.
If you can have all your classes derive from a common ancestor, you can provide a virtual function that accomplishes this. I haven't tried this template, it might not work - some feedback would be appreciated.
struct Reflector
{
virtual void Show() = 0;
};
template<class a, char name[]>
struct ReflectorImpl : public Reflector
{
virtual void Show()
{
std::cout << name << ": " << *this << std::endl;
}
};
class MyClass: public ReflectorImpl<MyClass, "MyClass">
{
};
Yes; in C++17 you can use PFR (in C++17 mode) to get nontrivial levels of non-macro reflection. There are related mechanisms for reflecting the "string-value" of an enum.
See https://github.com/apolukhin/magic_get ;
And https://github.com/Neargye/magic_enum .
I've a working logger class, which outputs some text into a richtextbox (Win32, C++).
Problem is, i always end up using it like this:
stringstream ss;
ss << someInt << someString;
debugLogger.log(ss.str());
instead, it would be much more convenient to use it like a stream as in:
debugLogger << someInt << someString;
Is there a better way than forwarding everything to an internal stringstream instance? If'd do this, when would i need to flush?
You need to implement operator << appropriately for your class. The general pattern looks like this:
template <typename T>
logger& operator <<(logger& log, T const& value) {
log.your_stringstream << value;
return log;
}
Notice that this deals with (non-const) references since the operation modifies your logger. Also notice that you need to return the log parameter in order for chaining to work:
log << 1 << 2 << endl;
// is the same as:
((log << 1) << 2) << endl;
If the innermost operation didn't return the current log instance, all other operations would either fail at compile-time (wrong method signature) or would be swallowed at run-time.
Overloading the insertion operator<< is not the way to go. You will have to add overloads for all the endl or any other user defined functions.
The way to go is to define your own streambuf, and to bind it into a stream. Then, you just have to use the stream.
Here are a few simple examples:
Logging In C++ by Petru Marginean, DDJ Sept 05th 2007
Rutger E.W. van Beusekom's logstream class, check also the .hpp alongside with this file
As Luc Hermitte noted, there is "Logging In C++" article which describes very neat approach to solve this problem. In a nutshell, given you have a function like the following:
void LogFunction(const std::string& str) {
// write to socket, file, console, e.t.c
std::cout << str << std::endl;
}
it is possible to write a wrapper to use it in std::cout like way:
#include <sstream>
#include <functional>
#define LOG(loggingFuntion) \
Log(loggingFuntion).GetStream()
class Log {
using LogFunctionType = std::function<void(const std::string&)>;
public:
explicit Log(LogFunctionType logFunction) : m_logFunction(std::move(logFunction)) { }
std::ostringstream& GetStream() { return m_stringStream; }
~Log() { m_logFunction(m_stringStream.str()); }
private:
std::ostringstream m_stringStream;
LogFunctionType m_logFunction;
};
int main() {
LOG(LogFunction) << "some string " << 5 << " smth";
}
(online demo)
Also, there is very nice solution provided by Stewart.
An elegant solution that also solves the flushing issues is the following:
#include <string>
#include <memory>
#include <sstream>
#include <iostream>
class Logger
{
using Stream = std::ostringstream;
using Buffer_p = std::unique_ptr<Stream, std::function<void(Stream*)>>;
public:
void log(const std::string& cmd) {
std::cout << "INFO: " << cmd << std::endl;
}
Buffer_p log() {
return Buffer_p(new Stream, [&](Stream* st) {
log(st->str());
});
}
};
#define LOG(instance) *(instance.log())
int main()
{
Logger logger;
LOG(logger) << "e.g. Log a number: " << 3;
return 0;
}
In the Logger class, override the << operator.
Click Here to know how to implement the << operator.
You can also avoid the logging statements inside the code
using Aspect Oriented programming.