In my code, I have a function:
template<typename T>
void foo (T*); // make sure that 'foo()' is passed only pointers
Now in new implementation, I am passing also a smart pointer (something like shared_ptr<>. So I have changed the signature of the function to,
template<typename T>
void foo (T); // pointers or smart-pointers
The code shall work fine. However, is there any side effect I am missing ?
You could use enable_if to only allow pointers or instances of shared_ptr to compile if you want. That way you can get back the compile-time checking you had before (though, presumably, your functions implementation would do that as well).
void foo(T) is pass-by-copy.
T& (pass by reference) would be more efficient if sizeof(T) is non-small.
Related
Suppose that I am implementing a collection and I want to add an element to it, something like.
template <typename T>
class MyCollection
{
void add(const T& element);
};
Now, since adding element usually means copying it, for efficiency reason it makes sense to have the
following version of add as well void add(T&& element). Now the problem is that, obviously the code for both functions is exactly the same, with only difference being the argument type. My command of C++ is limited at the moment, but I would like to know whether there is a simple and idiomatic way to write the addthe function once without rewriting it twice?
In fact this is solved by defining a single overload:
void add(T element) {
where_it_is_actually_stored.insert(std::move(element));
}
Next, depending on whether you're adding a lvalue, a rvalue made from a moved lvalue, or a temporary object, the compiler will resolve an appropriate constructor so your value argument would be either copied or moved.
The most general solution, I think, would actually be this. This is what the standard library provides, so I suppose that makes it "idiomatic".
template<typename T>
struct my_collection {
template<typename... Args>
void emplace(Args&&... args) {
// construct the T object directly in its place out of std::forward<Args>(args)...
}
};
I was in a position where I was using std::forward wherever I had a forwarding reference and I was wondering if some of that was unnecessary or even wrong. For example having std::forward in a std::begin() call.
Because of the ability of a class being able to overload its member functions based on whether the call is made with the object as an rvalue or not https://akrzemi1.wordpress.com/2014/06/02/ref-qualifiers/, I assumed that a templated function would be as efficient as possible if you were knew that the inner function you were forwarding the object to was non-mutating and/or was a member function of the object. For example
template <typename Something>
void do_something(Something&& something) {
std::forward<Something>(something).do_something();
auto iter = std::begin(std::forward<Something>(something));
for_each(iter, std::end(std::forward<Something>(something), []() {});
}
I saw this question (When not to use std::forward with r-values?) but it did not address the member function ref-qualifiers and it also did not clearly address what the best practice is when you don't have access to the inner functions definitions that you are calling.
Is there a general guideline for when not to use std::forward that addresses the things I mentioned? Or is there some key concept that I am missing?
Except if you know the type you will have, avoid to use std::forward several time in the same function for the same object, as the second time, your object might be moved.
// assuming implementation which really need pass by value instead of const reference
template <typename T> void pass_by_value(T t) { std::cout << t; }
template <typename T>
void foo(T&& t)
{
pass_by_value(std::forward<T>(t));
pass_by_value(std::forward<T>(t));
}
a call of foo with std::string
foo(std::string("Hello world")); // or "Hello world"s
might call the equivalent to
pass_by_value(std::string("Hello world"));
pass_by_value(std::string("")); // Moved string...
The problem is a use after object moved from ("stealed"). If something used in a multiple lines of do_something, then use std::forward only at the last such line to prevent the problem.
I'm developing a templated binary search tree in C++ for a data structures class right now. Everything has been going well until now. This issue deals with some nitty gritty C++ stuff that I'm not to familiar with, and I need help.
I've previously defined functions that traverse the tree and visit each node in different orders. The one in question here is defined as follows.
TreeNode.h
public:
static void PostOrderVisit(TreeNode<T>* node, void visit(const T& v));
TreeNode.cpp
template <class T> void TreeNode<T>::PostOrderVisit(TreeNode* node, void visit(const T& v)) {
if (node->leftChild != NULL)
PostOrderVisit(node->leftChild, visit);
if (node->rightChild != NULL)
PostOrderVisit(node->rightChild, visit);
visit(node->value);
}
This works fine in a test program that makes nodes and statically calls PostOrderVisit.
In a friend class (BinSTree.h/cpp), I am implementing a method that deletes every node in the tree, so I thought it would be a good idea to use this visitor and call my Delete() function on each node (the Delete() function also works fine in test programs for the BinSTree).
This function is defined as follows.
template <class T> void BinSTree<T>::ClearTree() {
TreeNode<T>::PostOrderVisit(this->root(), &BinSTree<T>::Delete);
}
And here lies the problem. g++ says...
BinSTree.cpp:156: error: no matching function for call to ‘TreeNode<int>::PostOrderVisit(TreeNode<int>*, void (BinSTree<int>::*)(const int&))’
TreeNode.cpp:56: note: candidates are: static void TreeNode<T>::PostOrderVisit(TreeNode<T>*, void (*)(const T&)) [with T = int]
In this case, I thought that void (BinSTree<T>::*)(const T&) would be an instance of void (*)(const T&), but it is not. The only way I can get the call to be recognized by the function definition is by casting the function pointer like this:
TreeNode<T>::PostOrderVisit(this->root(), (void (*)(const T& v)) &BinSTree<T>::Delete);
This recognizes the function and calls it appropriately, however (this took some significant research...), C++ member functions have an implicit parameter that allows the 'this' keyword to be accessed from within. Casting a member function pointer to a plain function pointer drops the 'this' reference altogether, causing my Delete() method to seg fault (it uses 'this' quite a bit).
This has been a HELL of a hassle, and I have spent quite a bit of time on such a small bit of this project. Can anyone show me a way to either A: make the function be recognized without the casting, or B: how to maintain the 'this' reference throughout the cast. The ClearTree() and Delete() methods are both within the same class.
Thanks in advance.
First of all, PostOrderVisit should take the function argument as a pointer, i.e. PostOrderVisit(TreeNode<T>* node, void (*visit)(const T& v)).
However, that wont solve your problem because you are passing it a non-static member function. Either the function you pass to it has to be static in the class, or you can use something like std::function instead of a function pointer argument, i.e. PostOrderVisit(TreeNode<T>* node, std::function<void(const T&)> visit).
Edit
In that case I think you have two ways you can do this: One is to change your design to fit the parameter, that means you can not use member methods as a parameter. The second is to change the code to fit your design, and explain to the teacher that you had to change the interface due to its limitations, and explain those limitations.
The problem with using a normal function pointer as argument is that member functions have an implicit and hidden argument, this, for the instance of the class. Normal functions do not have this hidden parameter, and so the compiler prohibits you from using a member function. The solution is to either use normal functions, which is not very C++-ish, another is to use static member functions (as they don't have a this pointer), or use something like std::function.
As for how to use std::function, you use it in the declaration and definition of PostOrderVisit like I've shown. When you call it you do something like this:
template <class T> void BinSTree<T>::ClearTree() {
TreeNode<T>::PostOrderVisit(this->root(), std::mem_fn(&BinSTree<T>::Delete));
}
Non-static methods take an implicit parameter for "this". E.g. for a method C::f(int i), you can think of it like f(C* this, int i). Any casting that you do and screws up this signature you can expect badness to happen. You have already experienced crashes but more sinister artifacts could make the program misbehave or crash at other seemingly random places.
You can use pointer to member function like this:
in .h
template <class C>
static void PostOrderVisit(C* node, void (C::* visit)(const T& v));
in .cpp (actually if it is a template it has all to be in h, otherwise link error)
template <class T>
template <class C>
void TreeNode<T>::PostOrderVisit(C* node, void (C::* visit)(const T& v))
{
// ...
T value;
(node->*visit)(value);
// ...
}
You either pass pointer to your derived class (C as in here) or pointer to base class (TreeNode as in original). At some point you may need to cast.
You can also leave original function for when you pass a normal function as visitor. Function overload would take care.
A more generic way can be to use std::function. Although it may have some minor performance hit it would be most generic.
e.g. (have not compiled may have some minor syntax errors):
static void PostOrderVisit(TreeNode<T>* node, std::function<void (const T& v)> visit);
Inside PostOrderVisit you just do visit(value), e.g. call like normal function.
When you call PostOrderVisit you can use all the power of std::bind or boost::bind to carry as much extra info as you wish. E.g.
PostOrderVisit(this->root(), std::bind(&BinSTree::Delete, this));
I have trouble compiling a class, which has function pointers as member variables. The pointers are to functions which take an instance of a class as argument.
Like
template<class T, int N>
double (*f)(Vector<T,N> v);
I get "error: data member 'f' cannot be a member template" Compiler is gcc 4.2.
Edit
Before using templates I just had
double (*f)(Vector v);
This also works
double (*f)(Vector<double,2> v)
But I would like to have a function pointer for a function which takes a generic Vector as argument..
Use a member typedef:
template <typename T, int N>
class Vector
{
public:
/// type of function pointer
typedef double (*FuncPtr)( const Vector& );
};
// concrete type
typedef Vector<double,10> VecDouble10;
// actual function
double func( const VecDouble10>& );
// usage
VecDouble10::FuncPtr fp = func;
If you want to have a "template pointer", you could try a function object. The example below adds 1.0 to the wrapped function template.
struct AcceptsVector {
template<typename T, int N>
double operator()(Vector<T,N> v) const { return 1.0 + real_f(v); }
};
AcceptsVector f;
The difference to a "real" template pointer is that you cannot re-seat "AcceptsVector" to call another template, like you can do with normal function pointers. The binding is hardcoded at compile-time. However you can pass along f like a function pointer, and can call f with any Vector<T, N> like a template.
That isn't quite valid c++, basically what you're looking for are template-template parameters.
http://www.progdoc.de/papers/ttp/psi-ttp/psi-ttp.html
explains all about them
Generally, if you get yourself into this situation, you want to find a workaroumd, because your code becomes illegible VERY quickly
Well, the compiler doesn't know at the compile time, how many f's are you going to have (one for each possible T and N?). Therefore the compiler cannot calculate how much memory do objects of your class need. That's why such constructs are prohibited.
You can't have a templated pointer to function, that makes no sense.
But what you can do is
#include <vector>
template <typename T>
void foo(const std::vector<T>& v) {
// do something
}
void (*ptr_foo)(const std::vector<int>&) = &foo<int>;
(here the function pointers a templated function, which template argument is explicitly set to int)
Because your code makes just as much sense as:
struct X
{
template < typename T >
std::vector<T> vect;
};
You're trying to make a member variable a template. This is just not a valid C++ construct and I seriously doubt it ever will be.
How do you do what you actually want? I'm not sure since I don't know what you actually are trying to accomplish and why.
I have a one-dimensional function minimizer. Right now I'm passing it function pointers. However many functions have multiple parameters, some of which are held fixed. I have implemented this using functors like so
template <class T>
minimize(T &f) {
}
Functor f(param1, param2);
minimize<Functor>(f);
However the functor definition has lots of crud. Boost::bind looks cleaner. So that I could do:
minimize(boost:bind(f,_1,param1,param2))
However I'm not clear what my minimize declaration should like like using boost::bind. What type of object is boost::bind? Is there an easy pattern for this that avoids the boilerplate of functors but allows multiple parameter binding?
You can just use boost::function. I think boost::bind does have its own return type, but that is compatible with boost::function. Typical use is to make a typedef for the function:
typedef boost::function<bool(std::string)> MyTestFunction;
and then you can pass any compatible function with boost::bind:
bool SomeFunction(int i, std::string s) { return true; }
MyTestFunction f = boost::bind(SomeFunction, 42, _1);
f("and then call it.");
I hope that is what you want.
It also works with methods by passing the this pointer for the call as second parameter to boost::bind.
I would define minimize() this way:
minimize(boost::function< return_type(param_type1,param_type2,param_type3,...)> f)
{
...
}
Then you could call minimize() like this:
minimize(boost::bind(&class::function,actual_object,_1,_2,_3,...));
Change the parameter to a value parameter. Function objects are intentionally light weight, and boost::bind certainly is, specially crafted to fit in within space of a few bytes using boost::compressed_pair and what not.
template <class T>
void minimize(T f) {
}
Then you can pass it the result of boost::bind. Remember that boost::bind is actually a function template that returns some object of some type. So having minimize have a non-const reference parameter couldn't work.
First, you are taking your template argument as a ref-to-non-const, so the temporary returend by boost::bind won't bind to it. So you can use it like:
template <class T>
T::result_type minimize(const T &f) {
}
But if you wanted to use this with your Functors as well, they would have to have a const operator(). So perhaps by value is better:
template <class T>
T::result_type minimize(T f) {
}
I believe having the return be T::result_type will force a T to be a boost::function (rather than the complicated type bind returns), but I'm not 100%