I have two classes
class MyStoreClass
{
public:
std::vector<std::unique_ptr<MyClass>> my_vec;
};
and
class MyClass
{
public:
double member1;
int member2;
};
I have a vector of around 10000 MyClasses
I would like to be able to use a function such as
template<typename T>
void MyStoreClass::output_member(T MyClass::* chosen_member)
{
std::cout << chosen_member << std::endl;
}
I'm not really sure where to go from here.
Edit: I'd like to output member from each MyClass in the vector
You forgot to describe what the function should do, so I'm assuming that you want the function to print the corresponding member of all elements of my_vec.
You need to explicitly dereference the unique_ptr in order to use the pointer-to-member dereferencing operator.
The rest is straightforward:
template<typename T>
void MyStoreClass::output_member(T MyClass::* chosen_member)
{
for (const auto& ptr: my_vec)
{
if (ptr)
std::cout << (*ptr).*chosen_member << std::endl;
else
std::cout << "[null]" << std::endl;
}
}
Continuing with the assumptions, I'm going to assume that by "standard" you mean "the pre-C++11 loop that I'm used to", since the range-based loop has been standard for quite a few years now.
template<typename T>
void MyStoreClass::output_member(T MyClass::* chosen_member)
{
for (std::vector<std::unique_ptr<MyClass>>::const_iterator i = my_vec.begin();
i != my_vec.end();
++i)
{
if (*i)
std::cout << (*i)->*chosen_member << std::endl;
else
std::cout << "[null]" << std::endl;
}
}
Related
I am new to coding and currently learning C++ to get started, so please excuse my narrow knowledge and very possible mistakes in code and general C++ lingo.
I have written a class of complex numbers called ComplexNumber with member variables being double re and double im with the obvious meanings. This class has a constructor, an empty constructor, a copy constructor, a destructor etc.
Using this I am now meaning to write a class ComplexVector of vectors with entries from ComplexNumber. For now I have defined the member variables to be a vector std::vector<ComplexNumber> vec and a size int size. Additionally I would like to define a member function void print(), again with the obvious meaning. The code I have so far is:
#include <iostream>
#include <vector>
#include "complex.h"
class ComplexVector {
private:
std::vector<ComplexNumber> vec;
int size;
public:
ComplexVector(std::vector<ComplexNumber> vector, int n){ //constructor
size = n;
vec = vector;
};
ComplexVector(){ //empty constructor
size = 0;
vec = {};
};
void print() const;
~ComplexVector(); //destructor
ComplexVector(const ComplexVector& v); //copy constructor
ComplexVector addition(ComplexVector w); //
ComplexVector subtraction(ComplexVector w); // i am not worrying about these for now
ComplexVector scale(ComplexNumber z); //
};
with defnitions
void ComplexVector::print() const {
for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){
std::cout << *it << " ";
};
std::cout << std::endl;
};
ComplexVector::~ComplexVector(){
std::cout << "calling destructor" << std::endl;
};
ComplexVector::ComplexVector(const ComplexVector& v){
size = v.size;
vec = v.vec;
};
Here is where I am getting a compiling error: in the definition of the print my compiler tells me
error: no viable conversion from '__wrap_iter<std::__1::vector<ComplexNumber, std::__1::allocator<ComplexNumber>
>::const_pointer>' to '__wrap_iter<std::__1::vector<ComplexNumber, std::__1::allocator<ComplexNumber> >::pointer>'
for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){
which I am not quite sure how to deal with. I have read something about certain member functions having to be defined for ComplexNumber to be used in an std::vector. I also played around with defining iterators inside of ComplexVector but this did not solve the problem. From my (to be fair very narrow) perspective there should be an iterator for vec and also corresponding begin()and end() functions. I have checked if I am passing arguments of the right type a thousand times, but I must be overlooking something.
One more thing to note is that I am very much aware that this is probably an extremely inefficient way to define a class like this. I have looked at multiple examples which used pointers to an array as the main member variable. I am surely going to implement something of that type next, but for now I want to understand where the mistake in my current code is. So thanks in advance for any answers.
One side question: I don't think I have understood the concept of a destructor very well (to be fair I haven't spent much time reading about it yet), but if anyone has a quick intuition about them, which he/she wants to share, that would be highly appreciated.
Also if you have any comments on style and/or other improvements of my code, I would appreciate it if you could share them.
Thank you!
Edit: Here is the ComplexNumberclass
class ComplexNumber {
private:
double re;
double im;
public:
ComplexNumber(double x, double y){
re = x;
im = y;
};
ComplexNumber(){
re = im = 0;
};
ComplexNumber(const ComplexNumber& z);
void print() const;
};
and definitions
void ComplexNumber::print() const {
if(im > 0){
std::cout << re << "+" << im << "i" << std::endl;
} else if(im < 0){
std::cout << re << im << "i" << std::endl;
} else {
std::cout << re << std::endl;
};
};
ComplexNumber::ComplexNumber(const ComplexNumber& z){
re = z.re;
im = z.im;
};
And a main method:
int main() {
std::vector<ComplexNumber> v1 = {ComplexNumber(1,2), ComplexNumber(4,2)};
int n = 2;
ComplexVector w1(v1,n);
w1.print();
return 0;
}
Your problem is here:
void ComplexVector::print() const {
for(std::vector<ComplexNumber>::iterator it = vec.begin(); it != vec.end(); it++){
std::cout << *it << " ";
};
std::cout << std::endl;
};
Notice that the function is marked const. This means any members of the class are treated as const qualified inside the method (i.e. you are not allowed to modify them). Thus when you call vec.begin() you are calling the const version of begin() on vector. This returns const_iterator not an iterator.
std::vector<ComplexNumber>::iterator it = vec.begin()
^^^^^^^^ should be const_iterator
A better way to solve this is to use auto and let the compiler work out the correct type:
auto it = vec.begin()
So the function becomes:
void ComplexVector::print() const {
for(std::vector<ComplexNumber>::const_iterator it = vec.begin(); it != vec.end(); it++){
std::cout << *it << " ";
};
std::cout << std::endl;
}
or with auto:
void ComplexVector::print() const {
for(auto it = vec.begin(); it != vec.end(); it++){
std::cout << *it << " ";
};
std::cout << std::endl;
}
or you can improve this by using the new version of for()
void ComplexVector::print() const {
for(auto const& item: vec){
std::cout << item << " ";
};
std::cout << "\n";
}
Note: When your code works. You can ask for a review on style at https://codereview.stackexchange.com
Follow up based on comments:
Try:
class ComplexNumber
{
......
friend std::ostream& operator<<(std::ostream& str, ComplexNumber const& data) {
data.print(); // You want to change this
// so you can pass the stream to print.
return str;
}
}
Based on this SO answer, I was experimenting with something similar but with a pointer:
#include <iostream>
class Bar {
public:
virtual ~Bar() {}
};
class Foo: Bar {
public:
Foo() { std::cout << "Foo::Foo()" << std::endl; }
~Foo() override { std::cout << "Foo::~Foo()" << std::endl; }
};
class Faz {
public:
Faz() { std::cout << "Faz::Faz()" << std::endl; }
~Faz() { std::cout << "Faz::~Faz()" << std::endl; }
};
template <typename T>
typename std::enable_if<std::is_base_of<Bar, std::remove_pointer<T>>::value>::type
func(char const* type, T) {
std::cout << type << " is derived from Bar" << std::endl;
}
template <typename T>
typename std::enable_if<!std::is_base_of<Bar, std::remove_pointer<T>>::value>::type
func(char const* type, T) {
std::cout << type << " is NOT derived from Bar" << std::endl;
}
int main()
{
func("std::unique_ptr<Foo>", std::unique_ptr<Foo>());
func("std::unique_ptr<Faz>", std::unique_ptr<Faz>());
}
cout is :
std::unique_ptr<Foo> is NOT derived from Bar
std::unique_ptr<Faz> is NOT derived from Bar
Why does !std::is_base_of<Bar, type_identity<std::remove_pointer<T>>>::value always evaluate as true? I assumed (as a beginner):
std::unique_ptr<Foo> is derived from Bar
std::unique_ptr<Faz> is NOT derived from Bar
I'm probably missing something stupid.
std::remove_pointer<> acts on raw pointer types.
The smart pointer's type is not related to the class hierarchy of referent type
I'm trying to write a simple function template in C++ in which I am printing out the value of a variable of unknown type. The problem is I can't figure out how to do this since the variable could either be a pointer or a primitive type. With the primitive type, I can simply print the value out; but pointers require de-referencing.
The following code gives me an error:
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
void foo(T someVar) {
if(std::is_fundamental<T>::value) {
cout << "It's primitive! \n" << someVar << endl;
} else {
cout << "It's a pointer! \n" << *someVar << endl;
}
}
int main(int argc, char **argv) {
int x = 5;
foo(x);
int *y = new int();
*y = 5;
foo(y);
delete y;
return 0;
}
The error I get when I compile is:
test.cc: In function 'void foo(T) [with T = int]':
test.cc:19:8: instantiated from here
test.cc:13:5: error: invalid type argument of unary '*' (have 'int')
It's complaining that I'm trying to de-reference a primitive type from my first call to foo(), but that's exactly why I'm using the if-statement: to check if it's primitive or not. How would I go about implementing what I'm trying to do?
What you need to do, is write 2 versions of your templated function.
template<typename T>
void foo(T someVar) {
cout << "Assume it's primitive! \n" << someVar << endl;
}
template<typename T>
void foo(T* pVar) {
cout << "This is a pointer! \n" << *pVar << endl;
}
The compiler will choose the pointer version if it works, because it's more specific. If the type is not a (raw) pointer, it will default to the first version.
If you need smart pointers to be dereferenced, you can further overload your function definition.
Eg.
template<typename T>
void foo(std::shared_ptr<T> pVar) {
cout << "This is a shared pointer! \n" << *pVar << endl;
}
You need an additional layer of indirection.
#include <iostream>
template < typename T >
struct print_helper
{
static void
print(std::ostream& os, const T& value)
{
os << "The value is " << value << "\n";
}
};
template < typename T >
struct print_helper< T * >
{
static void
print(std::ostream& os, const T *const pointer)
{
os << "The pointer points to " << *pointer << "\n";
}
};
template < typename T >
void
foo(T whatever)
{
print_helper<T>::print(std::cout, whatever);
}
int
main()
{
const auto a = 42;
foo(a);
foo(&a);
}
Output:
The value is 42
The pointer points to 42
A solution I'm partial to for just printing nicely is to write a function to do the dereferencing.
template<typename T> T &deref(T &elem) { return elem; }
template<typename T> T &deref(T *elem) { return *elem; }
Then you can simply use deref(value) anywhere you don't know whether or not value will be a pointer, as long as you don't care which it is.
template<typename T>
void print(T t) {
std::cout << deref(t) << '\n';
}
Write the function twice:
struct Foo
{
template<typename T>
static void foo(T val) {
cout << "var: " << val << endl;
}
template<typename T>
static void foo(T* val) {
cout << "ptr: " << *val << endl;
}
};
To call:
int x;
int *y;
Foo::foo(x);
Foo::foo(y);
I do not think "in place" is the right term, but I am lacking a better one.
I have a POD, let's say:
struct My {
int a;
};
//and suppose a operator<< to stream is also defined
And I may use it right this:
My my = {3};
std::cout << my << std::endl;
I am wondering if I can do the same below but without using a helper func:
template <typename ANY>
My helper(ANY value) {
My r = {value};
return r;
}
std::cout << helper(3) << std::endl;
I am looking for the same thing that a constructor does, but since I have a POD I can not create a constructor.
You can do this:
struct My {
int a;
int b;
int c;
float d;
};
void somefunc() {
cout << (My){1, 2, 3, 4.5} << endl;
}
I've looked over a few similar questions, but I'm still confused. I'm trying to figure out how to explicitly (not by compiler optimization etc) and C++03-compatible avoid copying of an object when passing it to a specialized template function. Here is my test code:
#include <iostream>
using namespace std;
struct C
{
C() { cout << "C()" << endl; }
C(const C&) { cout << "C(C)" << endl; }
~C() { cout << "~C()" << endl; }
};
template<class T> void f(T) { cout << "f<T>" << endl; }
// This shows two possible ways, I don't need two overloads
// If I do it like (2) the function is not called, only if I do it like (1)
template<> void f(C c) { cout << "f<C>" << endl; } // (1)
template<> void f(const C& c) { cout << "f<C&>" << endl; } // (2)
int main()
{
C c;
f(c);
return 0;
}
(1) accepts the object of type C, and makes a copy. Here is the output:
C()
C(C)
f<C>
~C()
~C()
So I've tried to specialize with a const C& parameter (2) to avoid this, but this simply doesn't work (apparently the reason is explained in this question).
Well, I could "pass by pointer", but that's kind of ugly. So is there some trick that would allow to do that somehow nicely?
EDIT: Oh, probably I wasn't clear. I already have a templated function
template<class T> void f(T) {...}
But now I want to specialize this function to accept a const& to another object:
template<> void f(const SpecificObject&) {...}
But it only gets called if I define it as
template<> void f(SpecificObject) {...}
Basically what I want to do with this specialization is to adapt the SpecificObject to the template interface like
template<> void f(SpecificObject obj){ f(obj.Adapted()); } // call the templated version
EDIT2: Ok, I can force the const C& specialization to be called this way:
f<const C&>(c);
but is there a way to make it work like this as just f(c)?
EDIT3: If someone would eventually have similar questions, I finally found this link in another question, and it is helpful: http://www.gotw.ca/publications/mill17.htm
You're conflating three issues: templates, overloading and argument passing.
Just remove the specializations and pass the argument as T const&.
Cheers & hth.,
Why don't you overload:
void f(const C& c) { cout << "f(const C&)" << endl; }
This would work:
int main()
{
C c;
f<const C&>(c);
return 0;
}
Your alternative:
template<typename T> void f(const boost::reference_wrapper<T const>& c)
{ cout << "f<boost_const_ref&>" << endl; }
int main()
{
C c;
f(boost::cref(c));
return 0;
}
In reality you would use boost::reference_wrapper to pass the reference through to where you want to use it. You can use get() to do that, although boost::reference_wrapper has an implicit conversion back to the reference, so you could probably get by without the partial-specialisation of the template and just passing boost::cref(c) to the regular one.
So if you don't always want to accept a const reference (which is reasonable for base types [int, long, float etc.]), you can use a little boost magic.
#include <iostream>
#include <boost/call_traits.hpp>
using namespace std;
struct C
{
C() { cout << "C()" << endl; }
C(const C&) { cout << "C(C)" << endl; }
//C& operator=(C const&) { cout << "C=C" << endl; return *this; }
~C() { cout << "~C()" << endl; }
};
template<class T> void foo(typename boost::call_traits<T>::param_type inst) { cout << "f<T>" << endl; }
// specialization for calling class C
template<> void foo<C>(boost::call_traits<C>::param_type inst) { cout << "f<C>" << endl; }
int main()
{
int i = 0;
foo<int>(i);
C c;
foo<C>(c);
return 0;
}
Your problem is that the actual parameter c isn't const, so the main template is a better match because it doesn't need to add 'const' to the type. If you try functions that pass by value and by non-const reference, the compiler will tell you that it cannot resolve that difference.
#include <iostream>
using namespace std;
struct C
{
C() { cout << "C()" << endl; }
C(const C&) { cout << "C(C)" << endl; }
~C() { cout << "~C()" << endl; }
};
template<class T> void f(const T&) { cout << "f<T>" << endl; }
int main()
{
C c;
f(c);
return 0;
}
This does do what you would like, but you must then use a const ref for all values passed into the function. I do not know if this was what you were looking for.