Template function overload resolution of T vs. SomeClass<T> - c++11

I want to understand why the void handleParam(const Str& name, Table<T> value) template overload never gets instantiated (note that the code below is illustrative). I'm sure there is a perfectly good reason why it doesn't work, I just want to understand that reason. I'm aware of (and using) the workaround using an intermediate templated struct. But if something like the below was possible it would simplify my code a lot.
class TypeHandler
{
public:
TypeHandler(OtherClass& bi) : _bi(bi) { }
template <typename T> void handleParam(const Str& name, Table<T> value)
{
// Never gets instantiated.
}
template <typename T> void handleParam(const Str& name, T value)
{
}
}
template<typename HandlerType>
void HandleParamValue::handleTab(DataBlock& data, HandlerType& handler) {
...
// Table of floats.
Table<float> tab;
handler.handleParam<Table<float>>(param_name, tab);
// etc.
...
}
template<typename HandlerType>
void ParamStore::Iterate(HandlerType& handler) {
for (...) {
...
if (is_table(type)) {
HandleParamValue::handleTab<HandlerType>(_datablock, handler);
}
else {
HandleParamValue::handle<HandlerType>(_datablock, handler);
}
}
}
// Kick the whole thing off.
TypeHandler handler(_some_instance);
_param_store->Iterate(handler);

The reason seems to be very simple: if you write
handler.handleParam<Table<float>>(param_name, tab);
you explicitly specify T = Table<float>. So handleParam(const Str& name, T value) is used. If you want to use handleParam(const Str& name, Table<T> value), you need to specify T = float:
handler.handleParam<float>(param_name, tab);
Or even
handler.handleParam(param_name, tab);
Because the compiler will select the most specialized version automatically.
I used the following code for testing:
#include <iostream>
#include <vector>
class TypeHandler
{
public:
template <typename T> void handleParam(const std::string& name, std::vector<T> value)
{
std::cout << "std::vector<T>\n";
}
template <typename T> void handleParam(const std::string& name, T value)
{
std::cout << "T\n";
}
};
template<typename HandlerType>
void handleTab(const std::string& name, HandlerType& handler) {
std::vector<float> tab;
handler.handleParam(name, tab);
}
int main()
{
TypeHandler t;
handleTab("dfds", t);
return 0;
}
If it doesn't reflect your problem adequately, please explain it in a comment.

Related

Template function taking generic pointer to member function with both const& and by-value implementations

I want to have a template function which accepts unary member-function pointers of an instance of some generic type.
My problem is that I must support both void(T val) and void(const T& val) member functions.
I have written one template function for each case and it works fine, but this leads to code duplication since the function logic is completely the same. (I found something completely similar here: Function taking both pointer to member-function and pointer to const member-function but I fail to see a definitive solution).
An example of the generic type mentioned above:
using UserAddress = std::string;
class User
{
private:
int mHeight;
UserAddress mAddress;
public:
void SetHeight(int height){mHeight = height;}
void SetAddress(const UserAddress& address){mAddress = address;}
};
Where UserAddress is some heavy type I want to pass by reference.
My templated function:
template <typename TPersistentObject>
class Persistence
{
private:
std::map<std::string, std::function<void(User*)>> mSetterOfProperty;
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(TPropertyValue), std::function<TPropertyValue(void)> dataReader)
{
mSetterOfProperty[propertyName] =
[propertySetter, columnDataReader](TPersistentObject* persistentObject)
{
(persistentObject->*propertySetter)(dataReader());
};
}
};
/// Const& implementation leading to code duplication
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(const TPropertyValue&), std::function<TPropertyValue(void)> dataReader)
{
...
}
};
Is there some way to define this function to support the following:
int main()
{
auto intDataReader = []() {
return 1;
};
auto stringDataReader = []() {
return UserAddress("Next Door");
};
Persistence p;
p.DefinePropertySettingMethod<User,int>("Height", &User::SetHeight, intDataReader);
p.DefinePropertySettingMethod<User,UserAddress>("Address", &User::SetAddress, stringDataReader);
}
Thanks to Igor Tandetnik 's tip I managed to compile a solution. std::enable_if is not what I needed though since I did not need to deactivate an overload (or at least I couldn't come to a solution using it).
std::conditional did the trick.
Here is the code:
#include <string>
#include <functional>
#include <map>
#include <string>
#include <type_traits>
using UserAddress = std::string;
class User
{
private:
int mHeight;
UserAddress mAddress;
public:
void SetHeight(int height){mHeight = height;}
void SetAddress(const UserAddress& address){mAddress = address;}
};
template <typename TPersistentObject>
class Persistence
{
public:
std::map<std::string, std::function<void(TPersistentObject*)>> mSetterOfProperty;
template <typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(TPropertyValue),
std::function<
typename std::conditional<!std::is_same<TPropertyValue, typename std::decay<TPropertyValue>::type>::value,
typename std::decay<TPropertyValue>::type, TPropertyValue>::type
(void)> dataReader)
{
mSetterOfProperty[propertyName] =
[propertySetter, dataReader](TPersistentObject* persistentObject)
{
(persistentObject->*propertySetter)(dataReader());
};
}
};
int main()
{
std::function<int()> intDataReader = []() {
return 1;
};
std::function<std::string()> stringDataReader = []() {
return UserAddress("Next Door");
};
Persistence<User> p;
p.DefinePropertySettingMethod("Height", &User::SetHeight, intDataReader);
p.DefinePropertySettingMethod("Address", &User::SetAddress, stringDataReader);
}

C++ Pass lambda to template parameter

How to pass lambda as template parameter.
For example this code
template<void (*callback)()>
void function() {
callback();
}
int main() {
function<[]() -> void { std::cout << "Hello world\n"; }>();
}
fails with error "invalid template argument for 'function', expected compile-time constant expression".
What I'm doing wrong.
Edit
I want to implement something like this
template<typename T,
T (*deserializer)(buffer *data),
void (*serializer)(T item, buffer *data)>
class Type {
public:
T item;
Type(T item) : item(item) {
}
Type(buffer *data) {
deserialize(data);
}
void serialize(buffer *data) {
serializer(item, data);
}
void deserialize(buffer *data) {
deserializer(data);
}
};
typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType
typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType
Lambdas in C++14, including their conversion to function pointers, are not constexpr.
In C++17, this is going to change. There are no stable compilers with that feature implemented that I'm aware of (if you find one, can you mention it in the comments below?).
At that point
constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; };
function<+tmp>();
will definitely work. I am uncertain if
function<+[]() -> void { std::cout << "Hello world\n"; }>()
would work; there are some rules about lambdas in unevaluated contexts and inside template argument lists that may be separate from the constexpr lambda problem and may apply here.
We can hack it in C++14.
Create a template class that stores a static copy of a lambda and exposes a static function with the same signature (f_ptr) that calls that static copy of a lambda.
Instantiate it once globally with your lambda.
Pass a pointer to the f_ptr to your template.
So:
template<class L> struct stateless; // todo
template<class L> stateless<L> make_stateless(L l){return std::move(l);}
auto foo = make_stateless( []() -> void { std::cout << "Hello world\n"; } );
function< &foo::f_ptr >();
this is almost certainly not what you want.
The kind of template in the example does not take a type as a parameter, but rather a value. This value needs to be determinable at runtime, in order to instantiate the template, and the value of a lambda is not a compile time constant, so this method just wont do. The common way of sending functors to a function is:
template<typename Func>
void foo(Func&& f)
{
f();
}
And since you want a class template (please put such information in the question, not the comments), here is an example using classes:
#include <utility>
template<typename Func>
class MyClass
{
public:
MyClass(Func&& f) : f(f) {}
void Run() { f(); }
private:
Func f;
};
template<typename Func>
MyClass<Func> MakeMyClass(Func&& f)
{
return { std::forward<Func>(f) };
}
int main()
{
auto x = MakeMyClass( [](){} );
x.Run();
}

c++11 segmentation fault while playing with variadic templates

So I was Playing around with c++11 Varidiacs, and I wanted to create a thing called CallClass, basically a class that warps a function, for later call,when all variables are set(truly I have No Idea If It can Be Useful):
#include <tuple>
template <typename OBJ,typename F,typename... VARGS>
class CallClass
{
public:
CallClass(OBJ& object,F callFunction)
:_object(&object),_func(callFunction)
{ }
CallClass(const CallClass& other)
:_func_args(other._func_args)
,_object(other._object)
,_func(other._func)
{ }
template <size_t INDEX>
auto get(){ return std::get<INDEX>(_func_args); }
template <size_t INDEX,typename T>
void set(const T& val){ std::get<INDEX>(_func_args) = val; }
template <size_t INDEX,typename T>
void set(T&& val){ std::get<INDEX>(_func_args) = val; }
auto Call()
{
//throws segmentation Fault Here
return InnerCall<0>(_func_args);
}
virtual ~CallClass() {}
protected:
private:
std::tuple<VARGS...> _func_args;
OBJ* _object;
F _func;
template <size_t INDEX,typename... ARGS>
auto InnerCall(std::tuple<VARGS...>& tup,ARGS... args)
{
auto arg = std::get<INDEX>(tup);
return InnerCall<INDEX + 1>(tup,args...,arg);
}
template <size_t INDEX,VARGS...>
auto InnerCall(std::tuple<VARGS...>& tup,VARGS... args)
{
return (_object->*_func)(args...);
}
};
Now when I try to compile(compiling using IDE:code::blocks, configured to use MINGW On windows ), it prints Compiler:Segmentation Fault, anybody any Ideas?
Usage:
class obj{
public:
obj(int a)
:_a(a)
{ }
virtual ~obj() {}
int add(int b,int c){
return _a + b + c;
}
private:
int _a;
};
int main(){
obj ob(6);
CallClass<obj,decltype(obj::add),int,int> callAdd(ob,obj::add);
callAdd.set<0,int>(5);
callAdd.set<1,int>(7);
cout << "result is " << callAdd.Call() << endl;
return 0;
}
After a Bit of a search i stumbled upon a similar issue, in a way.
apparently the way I'm unpacking the tuple is an issue, so i decided to use a different approach as shown in: enter link description here
had to add a few changes to suit my needs:
changes:
namespace detail
{
template <typename OBJ,typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static auto call(OBJ& obj,F f, Tuple && t)
{
return call_impl<OBJ,F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(obj,f, std::forward<Tuple>(t));
}
};
template <typename OBJ,typename F, typename Tuple, int Total, int... N>
struct call_impl<OBJ,F, Tuple, true, Total, N...>
{
static auto call(OBJ& obj,F f, Tuple && t)
{
return (obj.*f)(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename OBJ,typename F, typename Tuple>
auto call(OBJ& obj,F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
return detail::call_impl<OBJ,F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(obj,f, std::forward<Tuple>(t));
}
and changed Call():
auto Call()
{
std::tuple<VARGS...> func_args = _func_args;
return call(*_object,_func, std::move(func_args));
}
I will probably make a few more changes, like passing the tuple as a reference, and making the structs a part of my class.

Checking for method parameter at runtime with SFINAE

I know one could check the existence of a particular method using expression SFINAE in C++11 as follows.
What I can't find though, is an example to do the same, checking method arguments as well. In particular I would like to match a method that takes a const parameter.
#include <iostream>
struct A
{
void method() const
{
return;
}
};
template <typename T, typename = std::string>
struct hasMethod
: std::false_type
{
};
template <typename T>
struct hasMethod<T, decltype(std::declval<T>().method())>
: std::true_type
{ };
int main() {
std::cout << hasMethod<A>::value << std::endl;
}
In reality I would like the hasMethod:: to match
void method(const Type& t) const
{
return;
}
What is the syntax to pass to decltype?
I have tried:
struct hasMethod<T, decltype(std::declval<T>().method(const int&))>
: std::true_type
but it obviously doesn't work.

performing static cast from a non template base class to a templated derived class which has variadic template parameter (c++)

I wanted to store a vector of function pointers, each taking different no. of arguments in a class "Store". So, wrote a templated class "Func" that would store the function as a std::function and its arguments in a tuple.
I derived this "Func" class from a non-template base class "IFunc", so that i can store a vector of pointers to this base class in the class "Store".
template<typename... Args>
class Func : public IFunc
{
public:
std::function<void (Args...)> f;
std::tuple<Args...> args;
template <typename F,typename... Ar>
Func(F&& func,Ar&&... arg): f(std::forward<F>(func)),args(std::make_tuple(std::forward<Ar>(arg)...))
{
}
virtual ~NonMemfun()
{
}
//other methods to unpack the tuple and call the function
};
The IFunc class:
class IFunc
{
public:
Ifunc(){}
virtual ~Ifunc(){}
};
The Store class:
class Store
{
std::vector<Ifunc*> funcs;
public:
template<typename... Args,typename... Args2>
void registerfunc(std::string name,int runs,void(*f)(Args...),Args2&&... arg)
{
Func<Args2...>* sample = new Func<Args2...>(f,arg...);
Ifunc* fp = sample;
funcs.push_back(fp);
}
};
I want to iterate through the vector and call each function. To do that i need to do a static cast like this:
Func<>* der = static_cast<Func<>*>(funcs[0]);
When i try to do this, the cast doesn't happen properly. I cannot specify the template paramenters(variadics) since this class(Store) is not aware of them.
I am totally stuck at this place. Something is wrong with my design i guess. Can someone please suggest me a better way to do this. Thank you.
Rather than trying to do a cast from IFunc to Func<>, you should make a pure virtual function, Apply() in IFunc, which Func<> defines as apply(f, args...);. As you iterate over the vector of IFunc pointers, simply call IFunc->Apply(), which will dispatch to the Func<>::Apply() and do the actual apply.
I'm not much of a C++ programmer, but I think you may find this useful.
I'm sure you know that templates are a compile time thing in C++ so your functions need to be known at build time.
With that said, if you do know your functions and you just want to map them to say a string command and then dynamically bind arguments from something like a stream then this code should help you. It is actually able to use a dynamic_cast to retrieve the command from the map.
this snippet is from a school project I did a while back that had a similar goal:
#include <map>
#include <string>
#include <sstream>
#include <tuple>
using namespace std;
class Shell {
class Command {
public:
virtual ~Command() {};
virtual void executeWithArgStream(Shell*, istream& s)=0;
};
template <typename... ArgTypes>
class ShellCommand : public Command {
private:
// FIXME: its probably more apropriate for FuncType to return an int for exit code...
typedef function<void(Shell*, ArgTypes...)> FuncType;
FuncType _f;
tuple<ArgTypes...> args;
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { typedef seq<Is...> type; };
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
// template for functions with no arguments
parseArgs(istream& is, std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
parseArgs(istream& is, std::tuple<P...> & parts) {
// this is the magic bit that takes a tuple of pointers (representing the command arguments)
// created at compile time and creates new instances of each argument type and populates it from
// the given input stream :D
auto& part = std::get<I>(args);
// hmmm should we delete or recycle...
delete part;
part = new typeof(*part);
is >> *part;
parseArgs<I + 1>(is, parts);
}
template<int ...S>
void callFunc(Shell* shell, seq<S...>) {
_f(shell, get<S>(args) ...);
}
public:
static constexpr size_t numArgs = sizeof...(ArgTypes);
ShellCommand(FuncType f) : _f(f) {};
void operator()(Shell* shell, ArgTypes... args) {
_f(shell, args...);
};
void executeWithArgStream(Shell* shell, istream& s)
{
parseArgs(s, args);
callFunc(shell, typename gen_seq<sizeof...(ArgTypes)>::type());
};
};
private:
typedef shared_ptr<Command> CommandPtr;
typedef map<string, CommandPtr> FMap;
FMap _cmdMap;
ostream& _out;
istream& _in;
public:
Shell(istream& is = cin, ostream& os = cout)
: _out(os), _in(is)
{
// populate
_cmdMap.insert(pair<string, CommandPtr>("chdir", make_shared<ShellCommand<string*>>(&Shell::chdir)));
_cmdMap.insert(pair<string, CommandPtr>("list", make_shared<ShellCommand<>>(&Shell::list)));
_cmdMap.insert(pair<string, CommandPtr>("count", make_shared<ShellCommand<>>(&Shell::count)));
};
int run();
// FIXME: its probably more apropriate for execute to return an int for exit code...
template <typename... ArgTypes>
void execute(string& command, ArgTypes... args);
void executeWithArgStream(string& command, istream& istr);
// shell commands:
// any command parameters must be done as a pointer!
// the magic that parses string arguments into real types depends on it!
void list() {
list command
};
void chdir(string* dir) {
// chdir command
};
void count() {
// count command
};
};
template <typename... ArgTypes>
void Shell::execute(string& command, ArgTypes... args)
{
typedef ShellCommand<ArgTypes...> CommandType;
CommandType* c = dynamic_cast<CommandType*>(_cmdMap[command].get());
// TODO: neeed to diferentiate between invalid commands and some kind of dynamic_cast failure
if (c) {
(*c)(this, args...);
} else {
// dynamic cast failure
throw runtime_error("Broken Implementation for:" + command);
}
}
void Shell::executeWithArgStream(string& command, istream& istr)
{
Command* c = _cmdMap[command].get();
if (c) {
c->executeWithArgStream(this, istr);
} else {
throw runtime_error("Invalid Shell Command: " + command);
}
}
int Shell::run()
{
do {
string cmd, argString;
_out << _currentDir->name() << "> ";
_in.clear();
_in >> cmd;
if (cmd == "q") {
return 0;
}
if (_in.peek() == ' ')
_in.ignore(1, ' ');
getline(cin, argString);
if (_cmdMap[cmd]) {
try {
if (argString.length()) {
istringstream s(argString);
executeWithArgStream(cmd, s);
} else {
execute(cmd);
}
} catch (runtime_error& e) {
_out << e.what() << endl;
}
} else {
_out << "unrecognized command: " << cmd << endl;
}
} while (true);
}
int main(int argc, const char * argv[])
{
// start the interactive "shell"
Shell shell();
return shell.run();
}

Resources