I have to write a program working in general as a buffer. I created a class with some methods like AddToBuffer with overloads for char*, int, string, another instance of class etc. My task is also to create some operator overloads. So I came up with an idea to use + operator for adding to buffer, working same as AddToBuffer. Do I really have to create overloads for all parameters or can maybe 'alias' operator+ to AddToBuffer. Or maybe I should change all AddToBuffer to operator+?
Thanks in advance.
I expect you could do a template something like:
class someclass
{
...
template<typename T>
someclass operator+(T a)
{
return AddToBuffer(a);
}
...
}
Since you didn't explain exactly how AddToBuffer works, it's hard to say exactly what to call to make, etc
You can use function template http://en.cppreference.com/w/cpp/language/function_template.
Like this:
#include <iostream>
#include <string>
class MyBuffer
{
public:
void AddToBuffer (const std::string& str) {
}
void AddToBuffer (const char* str) {
}
void AddToBuffer (int i) {
}
template<typename T>
MyBuffer& operator+= (const T& str) {
this->AddToBuffer (str);
return (*this);
}
};
int main (int argc, char *argv[])
{
MyBuffer buffer;
buffer += std::string("abcd");
buffer += "abcd";
buffer += 1;
return(0);
}
Since others already answered the question (I think), I'll just add a few lines of personal experience:
Using operator overloads is cool. Using template classes is cool. Using polymorphism is waaaaaay cool. However, cooler doesn't make your code better; nor does shorter. There's a reason why you have string.operator+ but not queue.operator+. Operators are meant ONLY for times when you're doing something related to an operator. Adding stuff to a buffer isn't one of them. I'll give you an example. Compare this:
Stack b;
int i;
while ((i = --b) > 0)
b--;
b += i * 2;
to this:
Stack b;
int i;
while ((i = b.Peek()) > 0)
b.Pop();
b.Push(i * 2);
See the difference? Sure, it's cooler to override some operators and write code that no one can read, but code (at least useful code) isn't meant to be cool. It's meant to work, to be reusable, to be readable, etc. C++ is a very dangerous language in that it allows you to do virtually anything, and lets you get away with it. If you're not careful what you do, you might end up knee-deep in trouble, trying to get something to work that would have worked so much better had you just written it some other way. I've been there. Don't make the same mistake.
Related
So, I´d want to implement simple serialization for some int variables in C++ and I really don´t know how...
My goal is the following:
I essentially want to be able to convert any integer to binary, preferably with a simple function call.
// Here´s some dummy code of what I essentially want to do
int TestVariable = 25;
String FilePath = "D:\dev\Test.txt";
Serialize(TestVariable, FilePath);
// [...]
// at some later point in the code, when I want to access the file
Deserialize(&TestVariable, FilePath);
I already heard of libraries like Boost, but I think that´d be a bit overkill when I just want to serialize simple variables.
Already thank you in advance for your answers. :D
First of all, there is a little "inconsistency": you're asking for binary serialization, in something that looks like a text file. I will assume you really want a binary output.
The only thing to take care about when serializing integers is the endianness of the machine (even though most of machines are little endian).
In C++17 or lower the easiest way is a runtime check like
inline bool littleEndian()
{
static const uint32_t test = 0x01020304;
return *((uint8_t *)&test) == 0x04;
}
C++20 introduces a compile-time check so you can rewrite the previous as
constexpr bool littleEndian()
{
return std::endian::native == std::endian::little;
}
At this point what you want, is writing in a standard way all integers.
Usually BigEndian is the standard.
template <typename T>
inline static T revert(T num)
{
T res;
for (std::size_t i = 0; i < sizeof(T); i++)
((uint8_t *)&res)[i] = ((uint8_t *)&num)[sizeof(T) - 1 - i];
return res;
}
at this point your serializer would be:
template <typename T>
void serialize(T TestVariable, std::string& FilePath)
{
static_assert(std::is_integral<T>::value); //check that T is of {char, int, ...} type
static_assert(!std::is_reference<T>::value); //check that T is not a reference
std::ofstream o(FilePath);
if (littleEndian())
TestVariable = revert(TestVariable);
o.write((char *)&TestVariable, sizeof(T));
}
and your deserializer would be
template <typename T>
void deserialize(T *TestVariable, std::string FilePath)
{
static_assert(std::is_integral<T>::value);
std::ifstream i(FilePath);
i.read((char *)TestVariable, sizeof(T));
if (littleEndian())
*TestVariable = revert(*TestVariable);
}
Notice: this code is just an example that works with your interface, you just have to include <iostream>, <fstream> and if you're using the c++20 version, include <bit>
First let me laydown the reasons not to do this:
It will be not safe to reuse the files on a different machine
Speed could be much slower than any library
Complex type like pointer, maps or structure are very difficult to implement right
But if you really what to do something custom made you can simply use streams, here is an example using stringstream (I always use stringstream in my unit test because I want them to be quick), but you can simply modify it to use filestream.
Please note, the type must be default constructable to be used by deserialize template function. That must be a very stringent requirement for complex classes.
#include <sstream>
#include <iostream>
template<typename T>
void serialize(std::ostream& os, const T& value)
{
os << value;
}
template<typename T>
T deserialize(std::istream& is)
{
T value;
is >> value;
return value;
}
int main()
{
std::stringstream ss;
serialize(ss, 1353);
serialize(ss, std::string("foobar"));
std::cout << deserialize<int>(ss) << " " << deserialize<std::string>(ss) << std::endl;
return 0;
}
I am trying to write some templated functions that accept either a std::basic_string or a char array from which the basic_string could be constructed.
My current solution is:
#include <string>
template<typename CharT>
void foo(std::basic_string<CharT> str)
{
(void)str; // do something with str
}
template<typename CharT>
void foo(CharT const * arr)
{
return foo(std::basic_string<CharT>{arr});
}
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
foo(L"hello");
foo(std::wstring{ L"hello" });
}
But this means that for each function I have to write another function that calls the first one. That's pretty annoying; is there an easier way to do it? Maybe it could be a template deduction guide, but as far as I know it does not exist for functions, only classes.
The first templated function is not sufficient because the template deduction fails: the compiler cannot deduce CharT in std::basic_string<CharT> from CharT const *. That is why I need a simpler way to tell this to the compiler.
Just bite the bullet and use 2 overloads. Any clever solution (which as davidhigh showed do exist) will only add unnecessary complexity, potential for bugs and confusion to the next reader.
You only write once but read multiple times. The small incovenient of writing a 1 line of body overload is worth doing against an non-idiomatic convoluted smart way.
Don't get me wrong, I love to find these smart solutions in C++, but if I found this solution in a production code it would take me a few good minutes just to figure out what the heck it is and what does it do, only to find out it just does what should have been a very basic thing in a complex way, I would ... well let's just say I wouldn't say nice things about the author of the code. Being lazy when writing code will cost you times over when you maintain, debug, extend, or even use the code.
Write simple, idiomatic and easy to understand code!
After a bit more of research, the best option imo is to use the C++17 feature std::basic_string_view:
template<typename CharT>
void foo(std::basic_string_view<CharT> str)
{
(void)str; // do something with str ...
// while remembering that string_view does not own the string
}
So forget about the older explanation below if you have access to a C++17-compiler.
There are two cases here to consider. The first case is that you do not really want to do something special with the basic string, but rather you apply only methods also available for the char-array (and just want to make sure it's called correctly regardless of the parameters). In this case, I'd simply use a general template parameter:
template<typename string_type
/* possibly some SFINAE to allow/disallow certain types */>
auto foo(string_type s)
{
std::cout << s << std::endl;
}
Second case is that you really want to do some special operation on the string which is not present for the char array. In this case you need an overload for basic_string, but you probably want to write it only once and not for each and every function you use. This is what the following string_invoker class tries to do (but it still needs some improvement, just working on it):
template<typename method>
struct string_invoker_impl
{
string_invoker_impl(method m) : m(m) {}
template<typename CharT>
auto operator()(std::basic_string<CharT> str) const
{
return m(str);
}
template<typename CharT>
auto operator()(CharT const * arr) const
{
return operator()(std::basic_string<CharT>{arr});
}
//possibly further methods for non-const array's, modification, etc.
method m;
};
auto string_invoker = [](auto m) { return string_invoker_impl<decltype(m)>{m}; };
auto foo_impl = [](auto str) {std::cout<< str <<std::endl; };
auto foo = string_invoker(foo_impl);
//you can merge the previous two calls also in a single one:
//auto foo = string_invoker( [](auto str) {std::cout<< str <<std::endl; });
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
//foo(L"hello"); //need std::wcout, thus it fails with std::cout
//but it's no general problem, just overload your foo_impl function
//foo(std::wstring{ L"hello" });
}
DEMO
It might not be advisable according to what I have read at a couple of places (and that's probably the reason std::string doesn't do it already), but in a controlled environment and with careful usage, I think it might be ok to write a string class which can be implicitly converted to a proper writable char buffer when needed by third party library methods (which take only char* as an argument), and still behave like a modern string having methods like Find(), Split(), SubString() etc. While I can try to implement the usual other string manipulation methods later, I first wanted to ask about the efficient and safe way to do this main task. Currently, we have to allocate a char array of roughly the maximum size of the char* output that is expected from the third party method, pass it there, then convert the return char* to a std::string to be able to use the convenient methods it allows, then again pass its (const char*) result to another method using string.c_str(). This is both lengthy and makes the code look a little messy.
Here is my very initial implementation so far:
MyString.h
#pragma once
#include<string>
using namespace std;
class MyString
{
private:
bool mBufferInitialized;
size_t mAllocSize;
string mString;
char *mBuffer;
public:
MyString(size_t size);
MyString(const char* cstr);
MyString();
~MyString();
operator char*() { return GetBuffer(); }
operator const char*() { return GetAsConstChar(); }
const char* GetAsConstChar() { InvalidateBuffer(); return mString.c_str(); }
private:
char* GetBuffer();
void InvalidateBuffer();
};
MyString.cpp
#include "MyString.h"
MyString::MyString(size_t size)
:mAllocSize(size)
,mBufferInitialized(false)
,mBuffer(nullptr)
{
mString.reserve(size);
}
MyString::MyString(const char * cstr)
:MyString()
{
mString.assign(cstr);
}
MyString::MyString()
:MyString((size_t)1024)
{
}
MyString::~MyString()
{
if (mBufferInitialized)
delete[] mBuffer;
}
char * MyString::GetBuffer()
{
if (!mBufferInitialized)
{
mBuffer = new char[mAllocSize]{ '\0' };
mBufferInitialized = true;
}
if (mString.length() > 0)
memcpy(mBuffer, mString.c_str(), mString.length());
return mBuffer;
}
void MyString::InvalidateBuffer()
{
if (mBufferInitialized && mBuffer && strlen(mBuffer) > 0)
{
mString.assign(mBuffer);
mBuffer[0] = '\0';
}
}
Sample usage (main.cpp)
#include "MyString.h"
#include <iostream>
void testSetChars(char * name)
{
if (!name)
return;
//This length is not known to us, but the maximum
//return length is known for each function.
char str[] = "random random name";
strcpy_s(name, strlen(str) + 1, str);
}
int main(int, char*)
{
MyString cs("test initializer");
cout << cs.GetAsConstChar() << '\n';
testSetChars(cs);
cout << cs.GetAsConstChar() << '\n';
getchar();
return 0;
}
Now, I plan to call the InvalidateBuffer() in almost all the methods before doing anything else. Now some of my questions are :
Is there a better way to do it in terms of memory/performance and/or safety, especially in C++ 11 (apart from the usual move constructor/assignment operators which I plan to add to it soon)?
I had initially implemented the 'buffer' using a std::vector of chars, which was easier to implement and more C++ like, but was concerned about performance. So the GetBuffer() method would just return the beginning pointer of the resized vector of . Do you think there are any major pros/cons of using a vector instead of char* here?
I plan to add wide char support to it later. Do you think a union of two structs : {char,string} and {wchar_t, wstring} would be the way to go for that purpose (it will be only one of these two at a time)?
Is it too much overkill rather than just doing the usual way of passing char array pointer, converting to a std::string and doing our work with it. The third party function calls expecting char* arguments are used heavily in the code and I plan to completely replace both char* and std::string with this new string if it works.
Thank you for your patience and help!
If I understood you correctly, you want this to work:
mystring foo;
c_function(foo);
// use the filled foo
with a c_function like ...
void c_function(char * dest) {
strcpy(dest, "FOOOOO");
}
Instead, I propose this (ideone example):
template<std::size_t max>
struct string_filler {
char data[max+1];
std::string & destination;
string_filler(std::string & d) : destination(d) {
data[0] = '\0'; // paranoia
}
~string_filler() {
destination = data;
}
operator char *() {
return data;
}
};
and using it like:
std::string foo;
c_function(string_filler<80>{foo});
This way you provide a "normal" buffer to the C function with a maximum that you specify (which you should know either way ... otherwise calling the function would be unsafe). On destruction of the temporary (which, according to the standard, must happen after that expression with the function call) the string is copied (using std::string assignment operator) into a buffer managed by the std::string.
Addressing your questions:
Do you think there are any major pros/cons of using a vector instead of char* here?
Yes: Using a vector frees your from manual memory management. This is a huge pro.
I plan to add wide char support to it later. Do you think a union of two structs : {char,string} and {wchar_t, wstring} would be the way to go for that purpose (it will be only one of these two at a time)?
A union is a bad idea. How do you know which member is currently active? You need a flag outside of the union. Do you really want every string to carry that around? Instead look what the standard library is doing: It's using templates to provide this abstraction.
Is it too much overkill [..]
Writing a string class? Yes, way too much.
What you want to do already exists. For example with this plain old C function:
/**
* Write n characters into buffer.
* n cann't be more than size
* Return number of written characters
*/
ssize_t fillString(char * buffer, ssize_t size);
Since C++11:
std::string str;
// Resize string to be sure to have memory
str.resize(80);
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
or without first resizing:
std::string str;
if (!str.empty()) // To avoid UB
{
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
}
But before C++11, std::string isn't guaranteed to be stored in a single chunk of contiguous memory. So you have to pass through a std::vector<char> before;
std::vector<char> v;
// Resize string to be sure to have memor
v.resize(80);
ssize_t newSize = fillSrting(&v[0], v.size());
std::string str(v.begin(), v.begin() + newSize);
You can use it easily with something like Daniel's proposition
The ultimate goal of this is to have a function which can take a variable number of arguments of a certain type (the same type, not different types), that can be declared on the function call.
As I'm using Visual Studio 2010, I CANNOT do:
MyFunction({1,2,3});
In an earlier question which was answered, I found I could use boost::assign::list_of(), however I discovered later that this seems to have a bug of some kind if you try to pass it only one parameter.
So I did some more searching and found that I could use variadic functions to achieve what I was aiming for.
void TestFunction2<int>(int count, ...)
{}
However, I wanted to restrict it by type, so eventually found I could do this with templates:
template <class T>
void TestFunction(const T& count, ...);
template <>
void TestFunction<int>(const int& count, ...);
Unfortunately, varargs things like va_list do not apparently like references. The examples I saw to restrict types like this used const references. If I remove the const reference aspect of the count parameter, it works as I want, but I don't know if this is going to lead to horrible side-effects down the road, OR if this whole varargs thing is a bad idea to begin with.
So I guess my question is, is what I'm doing in the last example above good or bad? If it's bad, what is a good alternative so I can call a function with one or more parameters in-line like, say, int parameters?
What you want is std::initializer_list<T>, unfortunately this require C++11 support.
An alternative, that is nearly as elegant and easy enough to upgrade from, is to use an array:
#include <iostream>
template <typename T, size_t N>
void func(T (&s)[N]) {
for (size_t i = 0; i != N; ++i) {
std::cout << s[i] << '\n';
}
}
int main() {
int array[] = {1, 2, 3};
func(array);
}
When you move on to a compiler that supports initializer lists, this can be changed into:
#include <iostream>
template <typename T>
void func(std::initializer_list<T> s) {
for (T const& t: s) {
std::cout << t << '\n';
}
}
int main() {
func({1, 2, 3});
}
So both the function and call sites update will be painless.
Note: the call site could be made completely similar using a macro, I advise against such approach, the purported gain is not worth the obfuscation.
EDIT:
One more solution... if your compiler's IDE partially supports C++11, you may be able to initialize a std::vector at call time, i.e.
template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}
....
TestFunction(std::vector<int>{1,2,3});
Advantages to this approach are that STL automatically frees the allocated memory when the function goes out of scope.
If that doesn't work you can resort to a two liner...
template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}
....
std::vector<int> tmp(1,2,3);
TestFunction(tmp);
The big downside is that here the memory sits on stack until you leave that scope (or explicitly resize the vector to zero length.
Both approaches share some advantages... the count is built in and you have access to other useful member functions or affiliate methods (like std::sort).
......................................
Why not use variable arguments?
See the answer here, for example...
Is it a good idea to use varargs in a C API to set key value pairs?
On non-C+11 compliant compilers (like your IDE), you can try...
template <typename T>
TestFunction(const unsigned int count, T * arr)
TestFunction<std::string>(10, new string[] {"One", "Two", "Three"});
(Sounds like you can't use this in your IDE, but...)
If you're confident you're only compiling on modern machines and are primarily using simple types, this is best/most standards compliant solution...
As of C++11 you can use std::initializer which is in std::vector:
#include<vector>
template <typename T>
void TestFunction(const std::initializer_list<T>& v)
{ }
int main()
{
TestFunction<double>({1.0, 2.0});
return 0;
}
..........................
...however this requires your compiler to be C+11 so it's not perfectly portable. For anything other than simple types, it also becomes harder to read.
I realize you say on the function call, but you may want to rethink that from a readability and ease of coding approach.
I agree with part of your approach -- what you want is to use a template function (this handles the variable type). Before you call you initialize your collection of same-type elements into a temporary standard C array or a std::vector/std::list (STL's array wrapper).
http://www.cplusplus.com/doc/tutorial/templates/
http://www.cplusplus.com/reference/vector/
http://www.cplusplus.com/reference/list/
It's more lines of code, but it's much more readable and standardized.
i.e.
Rather than...
MyFunction({1,2,3});
Use:
template <typename T>
void TestFunction(const int count, T * arr)
{
for (unsigned int i = 0; i < count; i++)
{
.... arr[i] ... ; //do stuff
...
}
}
int main()
{
int * myArr = {1,2,3};
TestFuntion<int>(3, myArr);
}
...or...
#include <vector>
template <typename T>
void TestFunction(std::vector<T> vect)
{
for (unsigned int i = 0; i < vect.size(); i++)
{
.... vect[i] ... ; //do stuff
...
}
}
int main()
{
std::vector<int> myVect;
myVect.push_back(1);
myVect.push_back(2);
myVect.push_back(3);
TestFuntion<int>(myVect);
}
std::list would also be a perfectly acceptable, and may perform better, depending on your use case.
Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.