I want to eliminate the process consumed by a decision using pointers to member functions. I need to give user options to turn on or off domain checking for a function defined on a limited continues domain.
It's ok to have pointers to member functions when not using templates. But here I have to generalize my implementation.
Specifically I have three member functions in my class:
1.value is a member function returns value calculated by the member that function points to. The function is a function pointer wich points to either checkedValue or uncheckedValue.
2.checkedValue is a member function that calculates and returns the result, if input is in specified range. else throws a std::domain error.
3.uncheckedValue calculates and returns the result, regardless of domain.
template <typename T>
class IO
{
private:
typedef T (IO<T>::*functionPtr)(const std::string& name, const T& input) const;
functionPtr function;
bool domainValidation;
void setDomainValidation(const bool& value);
//...
public:
// ...
T value(const std::string& name, const T& input) const;
T uncheckedValue(const std::string& name, const T& input) const;
T checkedValue(const size_t& index, const T &input) const;
};
// Implementation:
template <typename T>
void IO<T>::setDomainValidation(const bool &value)
{
domainValidation = value;
if(domainValidation)
{
// function points to checkedValue()
function = & IO<T>::checkedValue; // Here I got undefinded reference error
}
else
{
// function points to uncheckedValue()
}
}
template <typename T>
T IO<T>::value(const string &name, const T &input) const
{
return (this->*function)(name,input);
}
template <typename T>
T IO<T>::uncheckedValue(const string &name, const T &input) const
{
// simply calculate and return the result
}
template <typename T>
T IO<T>::checkedValue(const string &name, const T &input) const
{
// if input is in domain, calculate and return the result
// else throw a std::domain error
}
This looks like a typo to me: The function signature of the function pointer is
...(const std::string &, const T &) ...
The signature of checkedValue is
...(const size_t &, const & T) ...
If the signature is changed to match the function pointer, the code sample compiles for me. Concerning the performance: Are you sure (as in have profiled or looked at the assembly) that the simple if-clause inside the value-method is worse than the (possible) indirection through a function pointer? Obviousl, the call to checked or uncheckedValue cannot be inlined.
Your function has signature
T checkedValue(const size_t& index, const T &input) const;
but not
T IO<T>::checkedValue(const string &name, const T &input) const;
Note the difference between the types of the first parameter.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm basically trying to create a thread-safe wrapper class for std::map.
As I'm coming from C, I have quite a hard time figuring out all the nuances of C++.
I'm trying to overwrite the [] operator to take std::string arguments to just pass it to my std::map member.
By the reference of std::map::operator[] this should work fine:
T& operator[]( const Key& key );
Here is my class:
thread_map.hpp
#ifndef THREAD_MAP_H
#define THREAD_MAP_H
#include <map>
#include <functional>
#include <mutex>
template <class T>class Thread_map
{
private:
std::map<std::string, T> map;
std::mutex map_mutex;
public:
~Thread_map();
T& at(size_t pos);
T& operator[](std::string &key);
size_t size() const;
bool empty() const;
void clear();
void insert(std::pair<std::string, T> pair);
T& erase(const std::string &key);
bool for_each(std::function<bool (Thread_map, std::string&, T&)> fun);
};
template<class T> Thread_map<T>::~Thread_map()
{
this->map.clear();
}
template<class T> T& Thread_map<T>::at(size_t pos)
{
T *value;
this->map_mutex.lock();
value = this->map.at(pos);
this->map_mutex.unlock();
return value;
}
template<class T> T& Thread_map<T>::operator[](std::string &key)
{
this->map_mutex.lock();
T &value = this->map[key];
this->map_mutex.unlock();
return value;
}
template<class T> size_t Thread_map<T>::size() const
{
size_t size;
this->map_mutex.lock();
size = this->map.size();
this->map_mutex.unlock();
return size;
}
template<class T> bool Thread_map<T>::empty() const
{
bool empty;
this->map_mutex.lock();
empty = this->map.empty();
this->map_mutex.unlock();
return empty;
}
template<class T> void Thread_map<T>::clear()
{
this->map_mutex.lock();
this->map.clear();
this->map_mutex.unlock();
}
template<class T> void Thread_map<T>::insert(std::pair<std::string, T> pair)
{
this->map_mutex.lock();
this->map.insert(pair);
this->map_mutex.unlock();
}
template<class T> T& Thread_map<T>::erase(const std::string &key)
{
T *value;
this->map_mutex.lock();
value = this->map.erase(key);
this->map_mutex.unlock();
return value;
}
template<class T> bool Thread_map<T>::for_each(std::function<bool
(Thread_map, std::string&, T&)> fun)
{
}
#endif
I put the implementation into the header file, because I heard you do that with template classes. Am I right on that?
My Problem is, that when I try to call the operator
Thread_map<std::string> map;
map["mkey"] = "value";
g++ throws an invalid initialization error on map["mkey"].
As far as my understanding goes the problem is that mkey gets compiled to std::string("mkey") which is just the value, not a reference.
But why or how does the following work then?
std::map<std::string, std::string> map;
map["mkey"] = "value";
I mean I could just pass the string by value but that seems inefficient.
Reference requires a variable's address that cans be modified. For lvalue string ("some string") there is no address that can be value modified.
There are some ways that I know to solve this issue:
Remove Reference (Not recommended)
One way is to remove the '&' from the parameter. like this:
T& operator[](std::string key);
In this way you don't request lvalue, but rvalue. The problem is that when ever you'll send a value, you won't send 4 bytes of memory address, but sizeof("Your string") bytes. Heavy method..
Make a const lvalue (Recommended way)
The most beautiful way to solve this issue, is to make the parameter const lvalue (what that called rvalue reference), to make a promise to the compiler that you won't try to change the given address's value inside this function. It's looks like this:
T& operator[](const std::string &key);
Now you can send a lvalue string and rvalue string.
Give up
This way is not bad as the first one, but absolutely not good as the second. You can easily use your declaration:
T& operator[](std::string &key);
And when you pass a value, use another string variable to store the value, and use this variable at call time:
Thread_map<std::string> map;
string key = "mkey";
map[key] = "value";
(Don't do that.. Just as extension for the knowledge).
I got this:
json& add(char* key, char* value) {
s.append("\"").append(key).append("\":\"").append(value).append("\",");
return *this;
}
json& add(char* key, const char* value) {
s.append("\"").append(key).append("\":\"").append(value).append("\",");
return *this;
}
template <typename vt>
json& add(char* key, vt value) {
s.append("\"").append(key).append("\":").append(std::to_string(value)).append(",");
return *this;
}
So 3 overloads for this function.
The first one is supposed to handle a char* value.
The last one is supposed to handle all the numeric types like uint_8t, int_8t, uint16_t .... float, double
if I use this function for example:
void test(json obj, char* value) {
obj.add("test", value);
}
Then everything works alright with just the first and the last overload. If I try to do this however:
void test(json obj) {
obj.add("test", "blah");
}
Then it will try to use the last overload (the one with the template) instead of the char* one since technically I'm passing a const char* to it.
So now I need to have the middle overload just for that.
Question is - is there a way to define a range of types for the template that its supposed to handle? To restrict vt to only the numeric types I mentioned? That should divert the compiler to use the char* overload instead and I wouldn't need the const char* one.
The non-const char* overload is not needed as you don't modify the parameter.
So the remaining ones are the second and the last version of you overload.
You stated that the templated overload is only meant for integral or floating point number types. I would recommend to use std::enable_if_t<> to restrict access to these types.
I would also recommend to make your key a const char*.
#include <string>
class json
{
private:
std::string s;
public:
json& add(const char* key, const char* value) {
s.append("\"").append(key).append("\":\"").append(value).append("\",");
return *this;
}
template <typename vt, typename = std::enable_if_t<std::is_arithmetic_v<vt>>>
json& add(const char* key, vt value) {
s.append("\"").append(key).append("\":").append(std::to_string(value)).append(",");
return *this;
}
};
int main(int, char**)
{
json j; double d = 0.1245;
j.add("Hello1", "World");
j.add("Hello2", 1234);
j.add("Hello3", 1234.1f);
j.add("Hello4", d);
}
The way to do it today is using enable_if and type traits. You want to define your template function as follows:
template <typename vt, typename = std::enable_if_t<std::is_arithmetic_v<vt>>>
json& add(const char* key, vt value) {
s.append("\"").append(key).append("\":").append(std::to_string(value)).append(",");
return *this;
}
Note this part: typename = std::enable_if_t<std::is_arithmetic_v<vt>>>
Hopefully in the next standard we will get concepts which will simplify this weird syntax.
If you are looking for more information, and background behind this technique, this is a very nice article: https://eli.thegreenplace.net/2014/sfinae-and-enable_if/
I have an abstract template class
template <typename T>
class Predicate1
{
public:
Predicate1();
virtual ~Predicate1();
virtual bool operator() (const T item) const = 0;
};
an implementation
class Pred : public Predicate1<string>
{
public:
virtual bool operator() (const string item) const;
};
bool Pred::operator()(const string item) const
{
return item == "";
}
and a template class with a method filter that takes a predicate:
template <typename T>
class TList : public boost::enable_shared_from_this<TList<T> >
{
public:
typedef boost::shared_ptr<const TList<T> > List;
const List filter(const Predicate1<T>& p) const;
...
};
I then use the filter as follows:
int main(int argc, char *argv[])
{
const TList<string>::List l1 = ...;
const TList<string>::List l2 = l1->filter(Pred());
}
which works OK.
However, I do not know how to replace the functor with an anonymous function.
I have tried:
const TList<string>::List l2 =
l1->filter([] (const string item) -> bool { return item == ""; });
The anonymous function has, as far as I understand, the same signature as the
functor's () operator, so it should work. Instead, I get the compiler error:
error: no matching function for call to ‘TList<std::basic_string<char> >::filter(main(int, char**)::<lambda(std::string)>) const’
note: candidate is: const TList<T>::List TList<T>::filter(const Predicate1<T>&) const [with T = std::basic_string<char>, TList<T>::List = boost::shared_ptr<const TList<std::basic_string<char> > >]
So, somehow the types seem to be incompatible, but I do not understand if I have overlooked something or what I am doing wrong. Or in other words, how do I have to declare the filter method so that it can (only) accept an anonymous function with signature
const string -> bool
or, in general, const T -> bool?
Instead of writing your own interface classes, use std::function:
const List filter(const std::function<bool (const T)>& p) const;
std::function has constructors from lambdas and functors, so you can continue to use Pred.
I'm building a series of predicates that duplicate lots of code, and so are being changed into a single template function class based on the std::unary_function. The idea is that my class interface requires methods such as Element_t Element() and std::string Name() to be defined, so the predicate template arguments are the object type and a value type to which comparison will be made as follows:
// generic predicate for comparing an attribute of object pointers to a specified test value
template <class U, typename R>
class mem_fun_eq : public std::unary_function <U*, bool> {
private:
typedef R (U::*fn_t)();
fn_t fn;
R val;
public:
explicit mem_fun_eq (fn_t f, R& r) : fn(f), val(r) { }
bool operator() (U * u) const {
return (u->*fn)() == val;
}
};
Thus, if I have:
class Atom {
public:
const Element_t& Element() const { return _element; }
const std::string& Name() const { return _name; }
};
I would like to perform a search on a container of Atoms and check for either the Name or Element equality using my template predicate like so:
typedef std::string (Atom::*fn)() const;
Atom_it it = std::find_if( _atoms.begin(), _atoms.end(), mem_fun_eq <Atom, std::string> ((fn)&Atom::Name, atomname));
but compiling this returns the following error on the std::find_if line:
error: address of overloaded function with no contextual type information
Also, trying to form the same predicate for a check of the Element() as such:
typedef Atom::Element_t& (Atom::*fn)() const;
Atom_it it = std::find_if(_atoms.begin(), _atoms.end(), mem_fun_eq <Atom, Atom::Element_t> ((fn)&Atom::Element, elmt);
creates a different error!
error: no matching function for call to ‘mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(Atom::Element_t& (Atom::*)()const, const Atom::Element_t&)’
note: candidates are: mem_fun_eq<U, R>::mem_fun_eq(R (U::*)(), R&) [with U = Atom, R = Atom::Element_t]
note: mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(const mem_fun_eq<Atom, Atom::Element_t>&)
Firstly, am I reinventing the wheel with this predicate? Is there something in the STL that I've missed that does the same job in a single class? I can always break the predicate down into several more specific ones, but I'm trying to avoid that.
Secondly, can you help me with the compiler errors?
I don't know of any easy way to do this using the bits provided with the STL. There is probably some clever boost way, using iterator adapters, or boost::lambda, but personally I wouldn't go that way.
Obviously C++0x lambdas will make all this easy.
Your problem is attempting to cast a function like this:
const std::string&(Atom::*)()
into a function like this:
std::string (Atom::*)()
If you replace your typedef R (U::*fn_t)(); with typedef const R& (U::*fn_t)() const; then it should work.
The following avoids this problem and also provides type inference so that you can just write mem_fun_eq(&Atom::Name, atomname). It compiles for me, although I haven't tested it.
template<typename U, typename R, typename S>
class mem_fun_eq_t : public std::unary_function<U const*, bool>
{
private:
R (U::*fn_)() const;
S val_;
public:
mem_fun_eq_t(R (U::*fn )() const, S val) : fn_(fn), val_(val){}
bool operator()(U * u)
{
return (u->*fn_)() == val_;
}
};
template<typename U, typename R, typename S>
mem_fun_eq_t<U, R, S> mem_fun_eq(R (U::*fn)() const, S val)
{
return mem_fun_eq_t<U, R, S>(fn, val);
}
Have you thought of trying to mix in a mem_fun_ref or mem_fun object in place of the member function call?
Basically, you call on mem_fun to create an object that accepts two arguments T* and a template argument to the function A if it has one (or void if it doesn't). Hence you combine it like so:
template<typename MemFunc, typename CompareType, typename T>
struct MyPredicate{
MyPredicate(MemFunc _functionObj, CompareType _value)
: m_Value(_value),
m_Function(_functionObj){}
bool operator()(const T &_input){
return m_Value == m_Function(_input);
}
private:
MemFunc m_Function;
CompareType m_Value;
};
Edit:
Ok, that's not completely working so why not have:
struct NamePred: binary_function<Atom*,string,bool>{
bool operator()(Atom *_obj, string _val){
return _obj->Name() == _val;
};
};
then use bind2nd
find_if( atoms.begin(), atoms.end(), bind2nd( NamePred, "yo" ) );
I have an interface
std::string
get_string(Source const &s, std::string const &d);
int
get_int(Source const &s, int const &d);
bool
get_bool(Source const &s, bool const &d);
which I'd like to change to
template<class T>
T
get(Source const &s, T const &d);
But there's no sensible base template, so the actual base definition is a legal but useless (return d;). What can I do to force compile-time failure if the base is instantiated? Is there an idiomatic solution for this situation?
Don't define the template, just declare it and define the three specializations.
template <typename T>
T get(Source const &, T const &);
template<>
std::string get(Source const &s, std::string const &d) {
return d + s.stringval(); // or whatever
}
[Edit: removed stuff about overloads - just for once, template function specialization does actually seem to be better. Who woulda thunk?]
just do
string get(source, string);
int get (source, int);
bool get(source, bool);
If you are willing to pay for run-time polymorphism, you can do this...
template <typename T>
class Interface
{
virtual T get(Source const &s, T const &d) = 0;
};
class StringInterface : public Interface<std::string>
{
virtual std::string get(Source const& s, std::string const& d);
};
// etc.
Since your base is an abstract class, you will get a compile-time failure if you try to instantiate it directly.
Declare the baseclass (t) as abstract, that way an instance can never be created of that class.