In an attempt to wrap some unmanaged code in a managed .dll I'm trying to convert a Generic::List of data points into a std::vector. Here's a snippet of what I'm trying to do:
namespace ManagedDLL
{
public ref class CppClass
{
void ListToStdVec( const List<double>& input_list, std::vector<double>& output_vector )
{
// Copy the contents of the input list into the vector
// ...
}
void ProcessData( List<double> sampleData )
{
std::vector<double> myVec;
ListToStdVec( sampleData, myVec );
// Now call the unmanaged code with the new vector
// ...
}
}
}
Compiling this gives me:
error C3699: '&' : cannot use this indirection on type 'const System::Collections::Generic::List'
I've probably missed something fundamental here (I'm relatively new to .net's way of doing things), but that looks like reasonably valid code to me.. ?
[Edit] I've tried both Andy and Dario's suggestions and they work, but how do I then access the members of the input list? I've tried all sorts of combinations of dreferencing and nothing seems to compile:
void ListToStdVec( const List<double>% input_list, std::vector<double>& output_vector )
{
int num_of_elements = input_list->Count;
}
void ListToStdVec( const List<double>^ input_list, std::vector<double>& output_vector )
{
int num_of_elements = input_list.Count;
}
...both give me:
error C2662: 'System::Collections::Generic::List::Count::get' : cannot convert 'this' pointer from 'const System::Collections::Generic::List' to 'System::Collections::Generic::List %'
...so how do you access the reference / pointer?
According to Herb Sutter, % is the managed object pass by reference character. Convert the code to the following, and it should work:
void ListToStdVec( const List<double>% input_list, std::vector<double>& output_vector
{
// Copy the contents of the input list into the vector
// ...
}
Edit: I think the const is causing the issues, although I'm not sure why. If you change the List argument to not be const, then the first function will compile if you use the -> operator, while the second function will compile if you use the . operator (I'm not sure why that difference exists - it doesn't make much sense).
That said, if all that you want to do is to copy the elements in the List to the vector, then you really want to use ^. Think of that as having a reference to the managed object. I think that % would be used if you want to pass the reference "by reference" (i.e. reassign input_list to something else within ListToStdVec(), and have the caller see the result of that assignment. However, given that you use the . operator to access members when using %, that tells me that I may not understand the purpose of that at all.
As List<T> is a managed .NET class, it's passed by managed GC-Handle denoted by ^ and not by C++-reference.
Ex:
void ListToVec(List<double>^ input_list, std::vector<double>& out)
You don't need additional const here. The notation List<T>^% creates a tracking reference (comparable to C++-pointers) rather than a call by reference.
Just access the members by list->... and list[...].
Related
I use std::vector<double> in some of my logic, but mainly the operator[]. Some data is coming from google's protocol buffer library in a repeated field. An example for the proto file:
message My_message{
repeated double numbers = 1;
}
So far I've only been using vectors, and converted the protobuf field to vector as described in another question.
void my_function(const std::vector<double> my_numbers){
...
double i_shall_copy_this = my_numbers[0];
std::copy(my_numbers.begin(),my_numbers.end(), inside_vector.begin());
...
}
int main(){
My_message my_msg;
...
std::vector<double> my_vec = {my_msg.numbers().begin(),my_msg.numbers().end()};
my_function(my_vec);
return 0;
}
Unfortunately this comes with unnecessary copying of data, which I would like to avoid. To avoid copying I would like to use references.
void my_function(const std::vector<double>& my_numbers){
...
}
int main(){
My_message my_msg;
...
my_function({my_msg.numbers().begin(),my_msg.numbers().end()}); //(1)
my_function(reinterpret_cast<std::vector<double>>(my_msg.numbers())); //(2)
return 0;
}
So far, adding it by temporary works( //(1) ), but it involves copying.
Despite the fact that both google::protobuf::RepeatedField and std::vecDor implements operator[], a reinterpret cast have failed //(2) :
error: invalid cast from type ‘const google::protobuf::RepeatedField<double>’ to type ‘std::vector<double>’
So a solution I have been thinking about is to add a third type, which requires only operator[] and the iterators implemented ( and a contiguous guarantee ).
Unfortunately common inheritance is not an option here: Both types come from official libraries, and I am just a mortal unworthy of maintaining a fork of those for a project. What options do I have here?
This is what templates are for. Since you only need the passed in type to have an operator[], you can make the function a template:
template<typename Container>
void my_function(const Container & my_numbers) {
// use my_numbers[42] for example
}
and now this will compile for any type that has operator[] defined for it.
So now there is no need to convert the google::protobuf::RepeatedField<double> to a temporary std::vector<double>.
I though that I understood iterators and addressing etc. but obviously not. See my below code below which is purely an example.
I need to be able to pass by pointer or reference each structure of mystructs to MyFunc(). The function should be able to update the actual structure that is passed, and not by copy or value.
I receive the compiler error :
error: cannot convert 'MY_STRUCT' to 'MY_STRUCT*' for argument '1' to 'void MyFunc(MY_STRUCT*)'
If I just pass the iterator address, this also doesn't work.
What is the correct way to do this. Thanks in advance.
typedef struct
{
int var1;
int var2;
std::string name;
}MY_STRUCT;
std::list<MY_STRUCT> mystructs;
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.end(); ++it)
{
MyFunc(*it);
}
Passing by reference in C++ is done with:
void MyFunc(MY_STRUCT&)
{
// Do something
}
So your call would be correct, what you currently want is to pass the pointer, which you can do with dereferencing the dereferenced iterator (by passing the address of the dereferenced object):
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
int main() {
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.begin(); ++it)
{
MyFunc(&*it);
}
}
Your function requires a pointer, use & to get the address of something.
MyFunc(&*it);
*it returns a reference to the MY_STRUCT object, you need to use & to convert that reference to a pointer. This is normal, the fact that you are using iterators makes no difference at all.
The alternative (maybe better in C++) would be to convert your MyFunc function to take a reference instead of a pointer.
What's the best course of action in C++ to take in the following situation?
My class has some double pointer as a private member:
class A
{
private:
int** data;
//...//
public:
int** get_data () const { return data; };
//...//
}
And sometimes I'd like to check the values inside this pointer and change them. And there's some get function get_data for this purpose:
A* obj = new A();
//...//
int** data_from_A = obj->get_data();
// some manipulations with data_from_A pointer
But what if I want to be confident that nothing won't change it in the further usage?
How is it better to get only the "read access" to the data pointer?
Of course, we can make the data pointer public, but in this case it can be changed from the outside, that is unacceptable...
Thanks!
In C++, raw pointers, and especially pointer arithmetics, should only be used buried deep deep within a class that utilizes them for high performance computing.
The only reason to give something like a pointer to an array to the outside is that you use some other code that would be tedious to rewrite, like a highly optimized solver written by somebody who is used to writing C style code (with the solver actually being in C maybe).
If not, go with a class from the standard library, like std::vector (dynamic), std::array (static) or std::list (linked).
This would transform your code to something like
private:
vector<vector<int> > data;
public:
const vector<vector<int> >& get_data() const { return data; }
Simple as that, one const totally suffices, none more required for sub-vectors as it would be with a raw array.
Another way would be to go with
const int& get_data(const size_t i, const size_t j) const { return data[i][j]; }
which would work even with your current code.
For the vector, remember that if you want to use it for a while, then you have to get it with
const vector<vector<int> >& data = myClass.get_data();
and not with either of those
vector<vector<int> >& data = myClass.get_data(); //compile error
vector<vector<int> > data = myClass.get_data(); //works but unnecessarily copies the data
The answer is to make "data" private and make the function which sets it up a "friend". Then the member is protected from access, except within your special function.
However friend functions are usually a sign of poor design, so you will probably want to look at refactoring to eliminate the need for this.
I have a function: Vector::Vector integrate(Vector::Vector start, Vector::Vector end, long int elapsedtime);, where a Vector is a class I've created:
class Vector {
public:
double x, y, z;
Vector();
Vector::Vector addToSelf(Vector &right);
};
I want to call integrate with a blank Vector for it's first parameter. The constructor for the Vector does this by default, so I'm trying to do this:
acceleration = integrate(Vector::Vector blank, wc.readAccelerometer(), time);.
However, this gives me errors:
error: expected primary-expression before ‘blank’.
I thought perhaps I didn't need to give the Vector a name when I create it in the integrate function call:
acceleration = integrate(Vector::Vector, wc.readAccelerometer(), time);
but this gives me the same error:
expected primary-expression before ‘,’ token.
I could always pass in a pointer, change the integrate signature to match, but this seems unnecessarily messy. I could also create a new Vector, then pass it to integrate:
Vector::Vector blank;
acceleration = integrate(blank, wc.readAccelerometer(), time);
which works without errors, but I would have thought doing it on one go would be possible. What am I doing wrong?
EDIT: Thanks to Karl von Moor's comment, I've fixed it - change Vector::Vector to Vector (because I'm not defining namespaces) and everything works. Thanks.
This line is not correct C++ syntax:
acceleration = integrate(Vector::Vector blank, wc.readAccelerometer(), time);
To create a default-constructed Vector object, use Vector():
acceleration = integrate(Vector(), wc.readAccelerometer(), time);
In C++11, you can also write Vector{} or even {} to construct a value-initialized object.
Note that usually you want to pass "large" objects by reference to const to avoid unnecessary copies. So try changing your declaration of integrate to:
Vector integrate(const Vector& start, const Vector& end, long int elapsedtime);
Don't use scope resolution operator in a class declaration and function's parameter names. So remove Vector:: until you are not defining the function. Example :
// declaration
class A {
A();
void f(int x);
};
// definitions
A::A(){/*...*/};
A::f(int x){/*...*/}; //note that the parameter x doesn't have a `::`
I'm new to this and now sure whether this is doable. I want to add a argument of std::set<std::string> to a function, and set its default value to be NULL, to avoid impact on previous uses.
So basically,
func(int a); turns into
func(int a, std::set<std::string> & temp = NULL);
but this will give me an error "error C2440: 'default argument' : cannot convert from 'int' to 'std::set<_Kty> &'"
Can anybody help me on this?
Thanks
In order to set the default to NULL, you'd have to be passing an std::set<std::string>*, not a reference to a value type.
Furthermore, if you are passing a non-pointer type and you want to assign any default value at all, it has to be a const reference, because you can't (advisably!) assign a temporary to it otherwise.
So your choices for "default" values are basically:
std::set<std::string>* = NULL
or:
const std::set<std::string>& = std::set<std::string>()
or option 3, using function overloading more directly:
void myfunction() {dothing(0);}
void myfunction(std::set<std::string>& optional_param)
{ dothing(optional_param.size()); }
or option 4, having a corresponding bool indicating whether parameter is "set":
void myfunction(std::set<std::string>& param, bool param_has_meaning=true) {}
It looks like you're already on the track to the third option. You just need to write two definitions, one with and one without the parameter.
You have the right idea - using a reference. However, a reference cannot be NULL by default, like a pointer can. Therefore, what you probably want to do is overload the function so that you use void func(int a) when you don't want to pass a set as a parameter and use void func( int a, std::set<std::string>& temp)
This way, you can actually provide two separate implementations - one that works on a set and one that doesn't. From a usage point of view, it would have the same effect as a default parameter. From a coding point of view, each implementation would have a clearer purpose.
If you're not going to be modifying the set, might I suggest using a const reference instead:
void func( int a, const std::set<std::string>& temp )
You can't have a NULL reference in C++.
The simplest way would be to have a dummy empty set:
std::set<std::string> empty;
void func(int a, std::set<std::string>& temp = empty)
{
// ...
}
You can then call:
func(1);
Neater, still, would be to use function overloading to create a wrapper so that you have no need to default:
void func(int a, std::set<std::string>& temp)
{
}
void func(int a)
{
std::set<std::string> empty;
func(a, empty);
}
// And then...
func(1);
All this assumes that if you pass in a set you're going to modify it somehow. It's not clear from your question what your intention is but I've made the assumption on the basis that your reference is non-const. If I've miscalculated, then the answer is even simpler:
void func(int a, const std::set<std::string>& temp = std::set<std::string>())
{
}
The following will give you an empty set object:
std::set<std::string>()