I am having trouble using function-objects in Visual Studio 2012.
I created a simple std::vector, added the ints 0-9 and wanted to create the sum of it using a function object. My class definition (inline):
template <class T>
class Sum {
private:
T val;
public:
Sum (T i = 0) : val(i) {
}
void operator()(T x) {
val += x;
}
T result() const {
return val;
}
~Sum() {
std::cout << "Invoked destructor! val: " << val << " for this: " << this << std::endl;
}
};
My main function:
int main(int argc, char *argv[]){
Sum<int> s;
int contents[] = {1,2,3,4,5,6,7,8,9};
std::vector<int> vec = std::vector<int>(contents, contents + 9);
std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s.result() << std::endl;
return 0;
}
Using the output from the destructor, I'll get:
Invoked destructor! val: 45 for this: 003BFDA4
Invoked destructor! val: 45 for this: 003BFDE0
Sum of all numbers: 0
Invoked destructor! val: 0 for this: 003BFEFC
Is this a bug from VS? Running through it using the debugger, the items are summed up to 45 but immediately afterwards the destructor is called. What am I doing wrong?
EDIT:
This is an example from Stroustrup's The C++ Programming Language, chapter 18.4. I just wondered it didn't work, as I copied it exactly.
The problem is that std::for_each accepts your functor argument by value. This means it works on a copy of your original object. The good news is that it also returns that copy which holds the modified state. This should do the trick:
Sum<int> s1 = std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s1.result() << std::endl;
Alternatively, you could let the val in your functor be a reference to some variable:
template <class T>
class Sum {
private:
T& val;
public:
Sum (T& i) : val(i) {
}
// ...
Now, this should work:
int i = 0;
Sum<int> s(i);
std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s1.result() << std::endl;
But you will have to take care of making sure that the lifetime of i is sufficiently extended not to make Sum<T>::val a dangling reference.
Related
I am implementing my own smart_pointer, which counts the references to the thing it points to. Here is my implementation so far:
#pragma once
#include <iostream>
template <typename T>
class smart_pointer{
T* pointer;
int* cnt;
public:
smart_pointer<T>(T *el): pointer(el) { int i = 1; cnt = &i; }; //
smart_pointer<T>(const smart_pointer<T>& other): pointer(other.pointer) {
// std::cout << ", *(other.cnt): " << *(other.cnt);
cnt = other.cnt;
(*cnt)++;
} // Copy-constructor
int counter(){
int c = *cnt;
return c;
}
};
In main.cpp, I did the following:
int main(){
// smart_pointer_examples();
std::string h("hello");
smart_pointer<std::string> p(&h);
std::cout << "p: " << p.counter();
smart_pointer<std::string> q(p);
std::cout << ", q: " << q.counter() << std::endl;
return 0;
}
The problem is that that outputs p: 1, q: 6487781. After a lot of time trying to find the issue by debugging and printing stuff, I found something that fixed my issue: By adding std::cout << ", *(other.cnt): " << *(other.cnt); somewhere in my copy-constructor, the output becomes p: 1, *(other.cnt): 1, q: 2, which is the desired behaviour. I can't for the life of me think of why printing the counter would change anything.
Edit: Also, if I only do *(other.cnt) without std::cout, the same problem that I started with happens.
You made a small mistake in implementing your idea.
I will not comment on the design of your smart pointer implementation.
The problem is that you implemented your counter as a pointer. That is wrong.
And, you are dereferencing a local variable. That is a semantic bug. The result is undefined. The value of the counter will be indeterminate. Additionally you should initialize your class members.
If we fix both, then your code will look like:
#pragma once
#include <iostream>
template <typename T>
class smart_pointer {
T* pointer{};
int cnt{};
public:
smart_pointer<T>(T* el) : pointer(el) { cnt = 1; }; //
smart_pointer<T>(const smart_pointer<T>& other) : pointer(other.pointer) {
// std::cout << ", *(other.cnt): " << *(other.cnt);
cnt = other.cnt;
cnt++;
} // Copy-constructor
int counter() const {
return cnt;
}
};
int main() {
// smart_pointer_examples();
std::string h("hello");
smart_pointer<std::string> p(&h);
std::cout << "p: " << p.counter();
smart_pointer<std::string> q(p);
std::cout << ", q: " << q.counter() << std::endl;
return 0;
}
I switched from c to c++ recently and just can't figure out what I'm doing wrong here.
I would like to access and set the member of a map via another function.
Here is my example which you can just copy to cpp.sh or so if you like
#include <iostream>
#include <map>
using namespace std;
struct test{
int i;
int j;
};
void addValues(test* val){
if (val == NULL){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
void printVal(test* val){
cout<<"finish " << val->i << " " << val->j;
}
int main()
{
map<string, test*> bla = {{"test1",NULL}};
addValues(bla.at("test1"));
printVal(bla.at("test1"));
return 0;
}
code from my project is a little bit more complex but it's basically this problem. I created a test in addValues() and have not deleted it. Why am I not able to print this value in printVal()? What am I missing?
Thanks in advance!
Parameters are passed by value. Pointers are no exception to that. Your addValues modifies a local copy of the pointer when a nullptr is passed. Modifying that local copy does not affect the pointer in the map. Pass the pointer by reference:
void addValues(test*& val){
if (val == nullptr){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
Or better yet, do not use raw pointers in the first place. Moreover, consider to write a constructor that initializes the members of test instead of relying on the caller to initialize them.
Example :
#include <iostream>
#include <map>
//using namespace std; NO teach yourself not to do this.
struct test
{
int i = 0; // <== in c++ you can initialize values of structs
int j = 0;
};
// this instead of printVal
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << "i = " << t.i << ", j = " << t.j << "\n";
return os;
}
int main()
{
std::map<std::string, test> map =
{
{"test1",{1,1}},
{"test2",{2,2}},
};
// loop over all entries in the map
// range based for loop.
// each entry in the map is a key,value pair (not they key, not the value but a pair)
// https://en.cppreference.com/w/cpp/language/range-for
std::cout << "range based for over keyvalue pairs\n";
for (const auto& kv : map)
{
// note kv.second is where we use operator<< from earlier.
std::cout << "Key : " << kv.first << ", value : " << kv.second << "\n";
}
std::cout << "\n";
// structured bindings make code more readable
// https://en.cppreference.com/w/cpp/language/structured_binding
std::cout << "range based for using structured bindings \n";
for (const auto& [key, value] : map)
{
std::cout << "Key : " << key << ", value : " << value <<"\n";
}
std::cout << "\n";
return 0;
}
I'm calling std::transform with a lambda that takes by reference and gives back a reference to the vector element. However, according to my program output, the copy constructor is called and the objects are NOT the same.
Code:
#include <algorithm>
#include <iostream>
#include <vector>
class Math
{
private:
int val_ = 5;
public:
Math(const Math& m) {
std::cout << "Copy constructor, our address: " << this << ", his address: " << &m << std::endl;
}
Math(int val) : val_(val) {
std::cout << "Object constructed with " << val << std::endl;
}
};
int main()
{
std::vector<Math> v_math = { { 5 }, { 10 } };
std::transform(
begin(v_math),
end(v_math),
begin(v_math),
[](const Math& m)-> const Math& {
return m;
});
}
Output (Godbolt):
Object constructed with 5
Object constructed with 10
Copy constructor, our address: 0x23d7ec0, his address: 0x7fff9dc499a8
Copy constructor, our address: 0x23d7ec4, his address: 0x7fff9dc499ac
So three things are unclear to me right now:
Why are the objects different? Shouldn't they be the same?
Why is one object's address bigger than the other? Is this because the copied-to object remains on the stack which has offset-pointers?
How can I avoid copy construction as well (actually I just "misuse" std::transform for a declarative way of invoking a lambda on every std::vector element)?
The copies have nothing to do with your usage of std::transform. They happen when you construct your v_math std::vector, because you're using a std::initializer_list constructor, which forces copies during construction.
In your std::transform call, operator=(const Math&) is called, change your code to the following to see this.
class Math
{
private:
int val_ = 5;
public:
Math(const Math& m) {
std::cout << "Copy constructor, our address: " << this << ", his address: " << &m << std::endl;
}
Math(int val) : val_(val) {
std::cout << "Object constructed with " << val << std::endl;
}
Math& operator=(const Math& other) {
val_ = other.val_;
std::cout << "Operator=(const Math&) called!\n";
return *this;
}
};
int main()
{
std::vector<Math> v_math = { { 5 }, { 10 } };
std::cout << "After constructing v_math!\n";
std::transform(
begin(v_math),
end(v_math),
begin(v_math),
[](const Math& m)-> const Math& {
return m;
});
std::cout << "After std::transform call!\n";
}
I have a templated class which wraps a std::vector called mObjects.
Class has an insert function which forwards parameters of the actually stored type in the MyArray instance (its called variadic template arguments I think). In this example, I store MyMesh type, but it can be any kind of type.
As you can see in the main() function, mObjects vector doesn't grow, its elements get overwritten over and over again.
Think about an object-pool kind of data structure.
Everything works as expected.
template <class T>
class MyArray
{
public:
MyArray(const int capacity) :
mObjects(capacity)
{
mNextIndex = 0;
}
template <typename... Args>
void insert(Args&&... args)
{
mObjects[mNextIndex] = T{ std::forward<Args>(args)... }; //PROBLEMATIC ASSIGNMENT
//... not relevant code
}
private:
int mNextIndex;
std::vector<T> mObjects;
};
int main()
{
MyArray<Mesh> sa(2);
sa.insert("foo",1111); //goes to mObjects[0]
sa.insert("bar",2222); //goes to mObjects[1], and tada, the vector is full
sa.remove(1111); //not implemented above, but not relevant. Remove func basically adjusts mNextIndex, so mObjects[0] will be overwritten upon next insert.
sa.insert("xxx",3333); //mObjects[0] gets overwritten from "foo" to "xxx" and 1111 to 3333
}
My problem is with one row above commented as //PROBLEMATIC ASSIGNMENT.
mObjects[mNextIndex] = T{ std::forward<Args>(args)... };
When that command executes 3 things happen:
MyMesh(const string s, int x) constructor is called, meaning an entire MyMesh gets allocated on stack here. Why? I just want to pass the forwarded arguments to an existing mObjects[mNextIndex] element.
operator=(MyMesh&& other) is called, and does assignment variable by variable between the temporary variable and mObjects[mNextIndex].
~cVMesh() is called meaning the temporary variable deallocates and dies.
I would like to get rid of #1 and #3. So don't want the "expensive" temporary object creation. I just wish to forward/assign the incoming MyMesh parameters to mObjects[mNextIndex]. Similarly like what std::vector.emplace_back() does, but to any location pointed by mNextIndex.
How can I forward only the parameters to an existing variable in C++, without instantiate temporary variables?
For completness, here is the MyMesh class which gets stored in the MyArray class. Nothing special just printing out some message, when constructor/destructor/assignement operator is called:
class Mesh
{
public:
Mesh()
{
cout << "Mesh()" << std::endl;
mStr = "";
mId = 99999999;
}
Mesh(const string s, int x)
{
cout << "Mesh(const string s, int x)" << std::endl;
mStr = s;
mId = x;
}
~Mesh()
{
cout << "~Mesh()" << std::endl;
}
Mesh& operator=(const Mesh& other)
{
cout << "operator=(const Mesh& other)" << std::endl;
cout << mStr << " becomes " << other.mStr << endl;
cout << mId << " becomes " << other.mId << endl;
mStr = other.mStr;
mId = other.mId;
return *this;
}
Mesh& operator=(Mesh&& other) noexcept
{
cout << "operator=(Mesh&& other)" << std::endl;
cout << mStr << " becomes " << other.mStr << endl;
cout << mId << " becomes " << other.mId << endl;
mStr = other.mStr;
mId = other.mId;
return *this;
}
Mesh(const Mesh& other)
{
cout << "Mesh(const Mesh& other)" << std::endl;
mStr = other.mStr;
mId= other.mId;
}
Mesh(Mesh&& other) noexcept
{
cout << "Mesh(Mesh&& other)" << std::endl;
mStr = other.mStr;
mId = other.mId;
other.mStr = "";
other.mId = 99999999;
}
string mStr;
int mId;
};
I think what you want is to reconstruct an arbitary element in the vector with new values
#include<vector>
template<class T, class... Args>
void create_at_nth_place(std::vector<T>& v, int n, Args&&...args){
auto& elem = v[n];
elem.~T();
new(&elem) T(std::forward<Args>(args)...);
}
struct S {
S();
S(int, bool);
template<class... Args>
S(Args&&...);
S(S&&) noexcept;
~S();
};
void f() {
std::vector<S> v(3);
create_at_nth_place(v, 2, 4323, false);
char a = 'a';
create_at_nth_place(v, 2, 'a', 123, 1232, 32.f, a);
}
Link: https://godbolt.org/g/3K9akZ
mObjects[mNextIndex] = T{ std::forward<Args>(args)... }; line creates a temporary object, performs a move(copy) assignment to object already stored in vector at specified position and finally destroys a temporary.
The whole MyArray class is rather useless since vector already has similar functionality.
vector<Mesh> sa;
sa.reserve(2);
sa.emplace_back("foo",1111); // Mesh constructor called once
sa.emplace_back("bar",2222); // Mesh constructor called once again
You might add:
void assign(const string& s, int x)
{
cout << "assign(const string s, int x)" << std::endl;
mStr = s;
mId = x;
}
And use it:
mObjects[mNextIndex].assign(std::forward<Args>(args)...);
If your mesh class is very heavy, you should consider having an array of pointers, this would eliminate spurious copies altogether. Wouldn't MyArray<std::shared_ptr<MyMesh>> work as is?
I'm trying to create a relatively type safe(but dynamic) and efficient concept called "Linkable Properties". A linkable property is similar to C#'s ability to bind properties and such and similar to the signal/slot model.
A linkable property is a type that can link itself to the values of other types. When any value changes all values are updated. This is useful when you need to keep several properties/values updated simultaneously. Once you setup a link everything is taken care of for you.
Can link from any type to any other type (in theory, this is the issue)
Links use a linked list rather than a list. This is more efficient both memory and speed and the real benefit of using this approach.
Converters are used to convert the values from one type to another(from 1, required, also an issue)
Can act like a getter and setter.
The issues I'm struggling with is writing the ability to link and convert to any type. The following code works with minor changes(convert the templated Chain function to a non-templated version and Change Chain<F> to Chain in the SetLink function). The problem is, the links are not correctly called.
This class almost works(it does compile and run but does not work as expected. Without the changes above the binding function never calls. It is only test code and not properly coded(please don't comment about using the static counter, it's just a temporary fix). The Chain and Link elements are the crucial aspect.
Chain is simply suppose to convert and update the value of the property then pass it along(or possibly the original value) to the next property. This continues until one reaches back to the original property in which case it will terminate.
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
static int iLCount = 1;
template <typename T>
class LinkableProperty
{
public:
std::string Name;
boost::function<void(T)> Link;
T Value;
template<typename F>
void Chain(F val)
{
Value = val;
std::cout << this->Name << " - " << this << ", " << &Link << ", " << val << " ! " << this->Value << " - " << "\n";
if (--iLCount < 0) return;
if (!Link.empty()) Link(Value);
}
LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };
void operator =(T value) { Value = value; }
template<typename F> void SetLink(LinkableProperty<F> &p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<F>, &p, _1);
}
void operator ()()
{
if (!Link.empty()) Link(Value);
}
};
int main()
{
LinkableProperty<unsigned short> L1;
LinkableProperty<double> L2;
L2.SetLink(L1);
L1.SetLink(L2);
L1 = 1;
L2 = 1.1;
L1();
cout << "----------\n" << L1.Value << ", " << L2.Value << endl;
getchar();
return 0;
}
The problem most likely stems from here:
template<typename F> void SetLink(LinkableProperty<F> p)
You are passing in a copy of the original property. Change this to accept a reference (or pointer), and you may have better luck. For example:
template<typename F>
void SetLink(LinkableProperty<F>* p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<F>, p, _1);
}
Should work as expected...
EDIT: Updated to show how to preserve the type across the conversion:
template <typename FT, typename TT>
TT convert(FT v)
{
return v; // default implicit conversion
}
template<>
double convert(unsigned short v)
{
std::cout << "us->d" << std::endl;
return static_cast<double>(v);
}
template<>
unsigned short convert(double v)
{
std::cout << "d->us" << std::endl;
return static_cast<unsigned short>(v);
}
static int iLCount = 1;
template <typename T>
class LinkableProperty
{
template <typename U>
struct _vref
{
typedef U vt;
_vref(vt& v) : _ref(v) {}
U& _ref;
};
public:
std::string Name;
boost::function<void(_vref<T>)> Link;
T Value;
template<typename F>
void Chain(F const& val)
{
Value = convert<typename F::vt, T>(val._ref);
std::cout << this->Name << " - " << this << ", " << &Link << ", " << val._ref << " ! " << this->Value << " - " << "\n";
if (--iLCount < 0) return;
if (!Link.empty()) Link(Value);
}
LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };
void operator =(T value) { Value = value; }
template<typename F>
void SetLink(LinkableProperty<F>* p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<_vref<T>>, p, _1);
}
void operator ()()
{
if (!Link.empty()) Link(_vref<T>(Value));
}
};
int main()
{
LinkableProperty<unsigned short> L1;
LinkableProperty<double> L2;
L2.SetLink(&L1);
L1.SetLink(&L2);
L1 = 1;
L2 = 1.1;
L1();
cout << "----------\n" << L1.Value << ", " << L2.Value << endl;
getchar();
return 0;
}
NOTE: There is some link bug which means that the updates trigger more times than necessary - you should check that...