C++ Template deduction while calling a template function - c++

FastDelegate refers to http://www.codeproject.com/KB/cpp/FastDelegate.aspx, but I don't think it is related.
I have code like following, and got error.
#include <FastDelegate.h>
using namespace fastdelegate;
template <typename T>
T Getter() {}
template <typename T>
void Setter(T) {}
template <typename T>
class Prop
{
public:
typedef FastDelegate0<T> Getter;
typedef FastDelegate1<T> Setter;
Prop(Getter getter, Setter setter) :
m_Getter(getter), m_Setter(setter)
{
}
private:
Getter m_Getter;
Setter m_Setter;
};
template <typename T>
inline Prop<T>* MakeProp(FastDelegate0<T> getter, FastDelegate1<T> setter)
{
return new Prop<T>(getter, setter);
}
static int Target = 0;
int main()
{
FastDelegate0<int> fdGetter(Getter<int>);
Prop<int>* c = MakeProp(fdGetter, Setter<int>);
// ^^^^ error: no matching function for call to 'MakeProp'
}
If changed the main() to:
int main()
{
FastDelegate0<int> fdGetter(Getter<int>);
FastDelegate1<int> fdSetter(Setter<int>);
Prop<int>* c = MakeProp(fdGetter, fdSetter); // It works.
}
or:
int main()
{
FastDelegate0<int> fdGetter(Getter<int>);
Prop<int>* c = MakeProp<int>(fdGetter, Setter<int>); // It works, too.
}
I think, MakeProp() should get the T from fdGetter (which is int, than called the contructor of FastDelegate1<int> automatically. But it did not. Why?
P.S. I would like to save the getter and setter in Prop, any suggestion for this approach is welcome. Maybe it is bad to copy the instance of FastDelegate* during passing arguments in function.

Have you tried
Prop<int>* c = MakeProp(FastDelegate0<int>(Getter<int>), FastDelegate1<int>(Setter<int>));
?
Setter<int> cannot be converted to FastDelegate1<T>!

Related

C++ templated class with different behaviour depending on type

say you have a class like this:
template <typename T>
class MyClass {
public:
void doSomething();
};
And within a method, is there any way to have different behaviour depending on the type like that:
template <typename T> MyClass::doSomething() {
//this is what I want:
std::string value = "17";
if(T == int) {
int myInt = atoi(value.c_str());
} else if(T == std::string) {
std::string myString = value;
}
}
Is there any easy way to achieve this?
I know I could write a wrapper class that provides a constructor that takes a std::string, so I could use something like:
T myVar(value);
But that would be more resource wasting if using simple type like an int, also I would like to realize that if-else-statement to be able to perform different actions.
I would be thankful for an answer.
regards,
tagelicht
In C++17, you can achieve exactly what you want with if constexpr(...):
template <typename T> MyClass::doSomething() {
//this is what I want:
std::string value = "17";
if constexpr(std::is_same_v<T, int>) {
int myInt = atoi(value.c_str());
} else constexpr(std::is_same_v<T, std::string>) {
std::string myString = value;
}
}
In C++14, you can implement your own static_if quite easily. I gave a tutorial talk about this at CppCon 2016 and Meeting C++ 2016.
template <typename T> MyClass::doSomething() {
//this is what I want:
std::string value = "17";
static_if(std::is_same_v<T, int>)
.then([&](auto) {
int myInt = atoi(value.c_str());
})
.else_if(std::is_same_v<T, std::string>)
.then([&](auto) {
std::string myString = value;
})();
}
In C++11, you probably want to use function overloading or template specialization. Example with the former (updated with suggestions from Jarod42 in the comments):
template <typename> struct tag { };
void call_dispatch(...) { } // lowest priority
void call_dispatch(tag<std::string>)
{
std::string myString = value;
}
void call_dispatch(tag<int>)
{
int myInt = atoi(value.c_str());
}
Usage:
template <typename T> MyClass::doSomething() {
//this is what I want:
std::string value = "17";
call_dispatch(tag<T>{});
}
Two approaches not yet exemplified are 1) tag dispatch and 2) template specialization
Tag dispatch:
Call a helper function that uses overloading
The way we do this is to define some empty templated struct as a lightweight "tag" type:
template <typename T>
class MyClass {
public:
void doSomething();
private:
// tag for dispatch
template<class U>
struct doSomethingTag{};
... and then define helper functions that take specializations of that tag:
void doSomethingHelper(doSomethingTag<std::string>, std::string value);
void doSomethingHelper(doSomethingTag<int>, std::string value);
};
Then we can use the primary entry point (doSomething) as a way to call the specialized helper function:
template <typename T>
void MyClass<T>::doSomething() {
//dispatch to helper function
doSomethingHelper(doSomethingTag<T>{}, "17");
}
Demo
The helper functions look like this:
template <typename T>
void MyClass<T>::doSomethingHelper(doSomethingTag<std::string>, std::string value)
{
int myInt = atoi(value.c_str());
}
template <typename T>
void MyClass<T>::doSomethingHelper(doSomethingTag<int>, std::string value)
{
std::string myString = value;
}
This should incur no overhead for the tag structures because the helper functions don't actually use the tag parameter, so it'll be optimized away. If it's not, it is a 1-byte overhead to construct the struct. (Note: Vittorio Romeo hinted at this in his answer, but he called it "function overloading")
Template specialization
You can "specialize" the template for your function so long as you are fully specializing it (specify the type for the class!):
The syntax for specialization looks a little strange because we keep the angle-brackets empty: <>:
template<>
void MyClass<int>::doSomething() {
//dispatch to helper function
std::string value = "17";
int myInt = atoi(value.c_str());
}
template <>
void MyClass<std::string>::doSomething()
{
std::string value = "17";
std::string myString = value;
}
This enables you to keep a smaller class:
template <typename T>
class MyClass {
public:
void doSomething();
};
Demo 2
Conclusion:
In the specific example you've given, I'd prefer template specialization. However, oftentimes you want to do some kind of partial specialization, and this gets very very strange with member functions, so tag dispatch is often preferred.
With C++17, using constexpr if definitely makes life easier.
How about this:
#include <type_traits>
template <typename T> MyClass::doSomething() {
//this is what I want:
std::string value = "17";
if(std::is_same<T,int>::value) {
int myInt = atoi(value.c_str());
} else if(std::is_same<T,std::string>::value) {
std::string myString = value;
}
}
This is C++11. You can make it even nicer with C++17 with constexpr if. Here there's the problem that you have to cast the values that are not implicitly castable. For example, return of std::string has to be cast to int for this to compile.

Cannot call generic std::function member from template class

When compiling the following code:
#include <functional>
template <typename functionSignature>
class Class
{
std::function<functionSignature> func;
public:
Class(const std::function<functionSignature>& arg) : func(arg) {}
void callFunc() { func(); }
};
void f(const int i) {}
int main()
{
Class<void(const int)> a(std::bind(f, 10));
a.callFunc();
return 0;
}
The VS 2015 compiler generates the following error message at the sixth line:
error C2064: term does not evaluate to a function taking 0 arguments.
Now, I believe this is because the compiler thinks functionSignature is not, well, a function signature; the same error happens when I instantiate and try to call operator() on an std::function<int> instead of std::function<int()>, for instance.
How can I guarantee that the template argument will always be a function signature, so that I can call operator() on the std::function?
I suspect you want something like that:
template <typename F>
class Class;
template<typename R, typename... P>
class Class<R(P...)> {
public:
std::function<R(P...)> func;
void callFunc(P... p) { func(p...); }
};
By using partial specialization that way you can easily define the type you want.
As an example, you can use it as:
Class<int(double)> c;
Of course, I noticed that you have no constructors for your class, so to invoke func is not a good idea, but it's quite easy to define it and pass a proper function as an argument.
It follows a complete and working example where I've used the operator() to invoke the function:
#include <functional>
template <typename F>
class Class;
template<typename R, typename... P>
class Class<R(P...)> {
public:
Class(std::function<R(P...)> f): func{f} { }
void operator()(P... p) { func(p...); }
private:
std::function<R(P...)> func;
};
void fn() { }
int main() {
std::function<void()> f = fn;
Class<void()> c{f};
c();
}
Your error is here:
Class<void(const int)> a(std::bind(f, 10));
The function Class::callFunc() invokes func() -- i.e., no arguments. The result of std::bind(f, 10) is also a function that takes no arguments, which is consistent with the template argument to the class template. Using Class<void(const int)> is inconsistent with both the usage in the class template and the initialization.
The solution is easy: Change the errant line to
Class<void()> a(std::bind(f, 10));
Is this what you are trying to do?
http://ideone.com/fork/IZ0Z1A
If functionSignature is NOT a function, std::function will throw errors when you create Class but you could add a constructor and throw there a static_assert(std::is_function<functionSignature>::value == true," ");if you want I guess.
#include <functional>
#include <iostream>
template <typename functionSignature>
class Class
{
public:
std::function<functionSignature> func;
void callFunc() { func(); }
};
void f()
{
std::cout << "hello" << std::endl;
}
int main()
{
Class<decltype(f)> t {f};
t.callFunc();
return 0;
}

Getting "illegal use of explicit template arguments" when doing a pointer partial specialization for a class method

Hello I'm having problems with partial specialization. What I want to do is have a class that has a template member function that will interpret a given value to one specified by the user. For instance the class name is Value and here is a snippet of what I want to do:
int *ptr1 = new int;
*ptr1 = 10;
Value val1 = ptr1;
int *ptr2 = val1.getValue<int*>();
Value val2 = 1;
int testVal = val2.getValue<int>();
Here is how I implemented such class:
struct Value {
Value(void *p) : val1(p){}
Value(int i) : val2(i){}
template<typename T>
T getValue();
void *val1;
int val2;
};
template<typename T>
T* Value::getValue<T*>() {
return reinterpret_cast<T*>(val1);
}
template<>
int Value::getValue<int>() {
return val2;
}
When I compile I'm getting the following error:
error C2768: 'Value::getValue' : illegal use of explicit template
arguments
Basically its complaining about the pointer template part of the code:
template<typename T>
T* Value::getValue<T*>() {
return reinterpret_cast<T*>(val1);
}
I know this problem can be implemented with a simple union, But this code is a stripped down version of a bigger code.
Does someone know what the problem could be? What I would like to do is separate one code for when using pointers and other for when not using pointers . I'm really stuck and I always investigate instead of asking, but I haven't found any good info about it.
Function templates cannot be partially specialised, but most of the time, you can use the delegate-to-class trick. In you example it would be like this:
struct Value {
template<typename T>
T getValue() {
return Impl_getValue<T>::call(*this);
}
};
template <typename T>
struct Impl_getValue
{
static T call(Value &v) {
//primary template implementation
}
};
template <typename T>
struct Impl_getValue<T*>
{
static T* call(Value &v) {
return reinterpret_cast<T*>(v.val1);
}
};

how to deduce the return type of a function in template

I am trying to write a template class named Binder that bind functions and parameters as whole, distinguished by the returning type of the binded function, this is my approach:
template <typename return_type>
class Binder
{
public:
virtual return_type call() {}
};
invoking call will invoke some pre-binded functions with parameters, and return the result.
I want some template classes inherited from Binder that do the real binding job.
below is a one-parameter-function binding class:
template<typename func_t, typename param0_t>
class Binder_1 : public Binder< ***return_type*** >
// HOW TO DETERMINE THE RETURN TYPE OF func_t?
// decltype(func(param0)) is available when writing call(),
// but at this point, I can't use the variables...
{
public:
const func_t &func;
const param0_t &param0;
Binder_1 (const func_t &func, const param0_t &param0)
: func(func), param0(param0) {}
decltype(func(param0)) call()
{
return func(param0);
}
}
// Binder_2, Binder_3, ....
This is what I want to achieve:
template<typename func_t, typename param0_t>
Binder_1<func_t, param0_t> bind(const func_t &func, const param0_t &param0)
{
reurn Binder_1<func_t, param0_t>(func, param0);
}
// ... `bind` for 2, 3, 4, .... number of paramters
int func(int t) { return t; }
double foo2(double a, double b) { return a > b ? a : b; }
double foo1(double a) { return a; }
int main()
{
Binder<int> int_binder = bind(func, 1);
int result = int_binder.call(); // this actually calls func(1);
Binder<double> double_binder = bind(foo2, 1.0, 2.0);
double tmp = double_binder.call(); // calls foo2(1.0, 2.0);
double_binder = bind(foo1, 1.0);
tmp = double_binder.call(); // calls foo1(1.0)
}
can bind function in boost library be adapted to achieve this functionality?
similar solutions are welcome too!
Introducing std::declval<T>().
This is a dummy function declared as:
template <typename T>
typename std::add_rvalue_reference<T>::type declval();
// This means it returns T&& if T is no a reference
// or T& if T is already a reference
and never actually defined.
It is therefore only to be used within unevaluated contexts such as sizeof or... decltype!
With this, you get:
template<typename func_t, typename param0_t>
class Binder_1: public Binder<decltype(std::declval<func_t>()(std::declval<param0_t>())>
It is a bit verbose, but hey! It works :)
You might be able to use result_of.

Function template as a parameter to a class template

<> - read this as a template;
I can do this:
void f() {}
//Here I'm declaring a fnc as a <> param
template<void (*fnc)()>
struct Factor { };
int main()
{
Factor<f> fac;
return 0;
}
but I cannot do this:
#include <sstream>
template<class R, class T>
R make_(T first, T second)
{
std::stringstream interpreter;
R result = R();
interpreter << first << '.' << second;
interpreter >> result;
return result;
}
//Here I'm (trying) to declare fnc <> as a <> param
template<template<class T,class R> R (*fnc)(T,T)>
struct Factor { };
int main(int argc, char* argv[])
{
Factor<make_> fac;
return 0;
}
The BIG Q is: How (if possible) can I declare as a template parameter a fnc template?
Edit
Providing that I've used Armen's advise:
I would like to be able to do something like this (in main):
Factor<f<"1","02">> m;
Then in m I could make a double type out of those args ("1", "02")
There is no syntax for that in C++.
What you should do is instead of function template use functor template, which would fit as a template template parameter.
E.G.
template <class R, class T>
struct f
{
R operator () (T const&)
{
//blah
}
};
template <template<class R, class T> class F >
struct foo
{
///...
};
int main()
{
foo<f> d;
}
Your syntax has some issues. What you do at the end with Factor<make_> fac; is similar to declaring vector<map> v; You need to provide parameters to the template to make it concrete: Factor<make_<int,int> > fac;. But that isn't the whole issue; there are many.
What you're doing with your function isn't quite right. You are providing a specific function (f in the first example), which can be done as a constructor parameter. You should reevaluate your design.
From looking at your make_() function template, it seems that what you actually want is boost::lexical_cast<>(). It does what your make_() does, only better. (For starters, your conversion doesn't check for errors at all.)