It follows a minimal example of the bind function in use.
It compiles and it is pretty trivial an example indeed.
#include <functional>
void fn(int i) { }
int main() {
int x = 0;
auto f = std::bind(fn, x);
}
I would be interested in doing the same with a templated function.
It follows the example above, even though slightly modified. This one doesn't compile, but it explains exactly which is the intended behavior.
#include <functional>
template<typename T>
void fn(T t) { }
int main() {
int x = 0;
auto f = std::bind(fn, x);
}
Quite simple a question: is it possible to use bind utility with a templated function?
I think the obvious solution is the code below.
#include <functional>
template<typename T>
void fn(T t) { }
int main() {
int x = 0;
auto f = std::bind(fn<int>, x);
}
If you don't want to be specific about the instantiation, maybe you can add one more template level. I'm making some tests.
EDIT: I spent a few hours thinking by myself, googling around and reading my printed TC++PL4Ed, as well as reading the implementation of GNU's libstdc++ source code, and I didn't figure nor did I find out how to do what you asked.
It turns out that when you made fn the name of a template, it could no longer be used as the name of an object. Since std::bind deduces its return type from (the types of) its arguments, the use of just fn became invalid. To have a callable object that qualifies as first argument to std::bind, you must now instantiate the template fn.
Related
I am trying to write a general integral function and I would like to implement it in such a way so that it can accept any mathematical function. That is, I would like to pass the math function as an input parameter. In pseudo-code: simpson_int(x*x). I've heard of the function template in <functional> but I don't really have experience with templates in C++.
There are some solutions that comes in my mind (and this is my approach at the problem, for sure there are more solution, and maybe what I'm pointing out is not the best), that consider the fact that you need to call the argument function more than once in the Simpson implementation (thus you need a "callable" argument):
Function pointer
Function pointers (more C than C++), where you declare with two arguments: the first one will be the pointer to a function with the specified types, while the second is the argument for your function. Lets
make an example:
#include <iostream>
double power2(double x) {
return x * x;
}
double simspon(double (*f)(double), double x) {
return f(x);
}
int main() {
std::cout << simspon(power2, 2);
return 0;
}
In this case I have used no templates for reaching the result. But this will not take any function as first argument, but only a function that has as argument a double and returns a double.
I think that most of c++ programmer will suggest you to avoid this method.
Function pointer and templates
So you maybe want to expand the previous example using templates and making it more general. It is quite simple to redefine the function
to accept a template (an abstract type) that you actually specify only when you use it in your code:
#include <iostream>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(T (*f)(P), P x) {
return f(x);
}
int main() {
std::cout << simspon<double, double>(power2, 2.0);
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
T and P are two templates: the first one is used for describing the returned value of the function pointer, while the second specify the argument of the function pointer, and the returned value of simpson.So when you are writing template <class T, classP> you are actually informing the compiler that that you are using T and P as placeholder for different type. You will actually declare the type that you want later on, when you will call the function in the main. This is not good code but I'm building the path to understand templates. Also, you specify the type of your argument function when you actually call simpson, with the < >.
(Disclaimer: you should consider to use template <typename T ...> instead of class. But I'm used with the old class and there are situation in which typename cannot be used, there are a lot of questions on SO that dive into this.)
Using std::function
Instead of using a function pointer as argument you may want to create a variable that stores your function to be passed as argument of simpson. This bring several advantages, because they are actually an object inside your code that have some predictable behavior in some unwanted circumstances (for example, in case of a null function pointer you have to check the pointer itself and handle it, in case of std::function if there is no callable pointer it throws std::bad_function_call error)
Here an example, and it uses again templates, as before:
#include <iostream>
#include <functional>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(std::function<T(P)> f, P x) {
return f(x);
}
int main() {
std::function<double(double)> p_power2 = power2;
std::cout << simspon<double, double>(p_power2, 2.0);
std::function<double(double)> p_power2int = power2int;
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
Using lambdas
lambdas are closure and in your case (if you can use the standard C++14) can be used alongside the auto keyword to achieve quite a general behavior, without the explicit use of templates. The closure are also able to capture part/the whole context, check the reference for this.
Let's see an example, in which I create two lambdas that receive different arguments and a simpson function that is quite general (actually it is not, is the compiler that defines different functions with respect to the call that you do).
#include <iostream>
auto lambda = [](auto x) { return x * x ; };
auto lambda_2 = [] (int x) { return x + 10; };
auto simpson(auto f, auto x) {
return f(x);
}
int main() {
std::cout << simpson(lambda, 2.0);
std::cout << simpson(lambda_2, 1);
return 0;
}
You need to compile it with the -std=c++14 flag. There are tons of advise that comes in my mind to suggest you to avoid to implement your code in this way, remember that it has only some illustrative purposes (I've more than exaggerated with the auto keyword).
Function objects (the Problem class)
Maybe an improvement for your case is to write a general class for the mathematical functions to integrate and pass the object to your function. This bring several advantages: you may want to save some of the integrative result inside your function or even write the stream operator to pretty print your problem. This is the solution employed typically by mathematical libraries.
In this extremely simple case, we have a class that is a problem. When you create a new instance for this class, a std::function is passed to the constructor and stored inside the class. The instance of the class is the argument for your simpson:
#include <iostream>
#include <functional>
template <class T, class P>
class Problem {
public:
// Attributes
std::function<T(P)> _f;
// Constructor
Problem(std::function<T(P)> f) : _f(f) {};
// Making the object callable
P operator()(P x) { return _f(x); }
};
template <class T, class P>
P simspon(Problem<T, P> p, P x) {
return p(x);
}
int main() {
Problem<double, double> prb([](double x) { return x * x; });
std::cout << simspon<double, double>(prb, 2);
return 0;
}
Use std::function, like this for example:
#include <iostream> // std::cout
#include <functional> // std::function
int main()
{
std::function<double(double)> simpson_int =([](double x) { return x * x; };
std::cout << "simpson_int(4): " << simpson_int(4) << '\n';
return 0;
}
which outputs:
simpson_int(4): 16
In the following code, I have a variable called data. It holds a functions inside itself to call them later. Let's assume data is defined in another library and I cannot change its type. I assign a template function to each member of it where a portion of this function is known (s3) and a portion must be given when it is called (true). I cannot pass something like this:
data[0]=test_func(?,s3); // error
instead, I have to pass a lambda function to it :
data[0]=[](bool b){test_func(b,s3);}; // ok
But the lambda function does not look neat especially when we have an array of 100 of these assignments. It there any way to avoid lambda functions by just changing the test_func in any way? even using lambda inside test_func is ok to me because it is just written once.
#include <iostream>
#include <functional>
template<typename F>
void test_func(bool b,F f)
{
if(b)
f();
}
void s1()
{
std::cout<<"s1 \n";
}
void s2()
{
std::cout<<"s2 \n";
}
void s3()
{
std::cout<<"s3 \n";
}
int main()
{
test_func(true,s1);
test_func(true,s2);
test_func(false,s1);
test_func(true,s2);
/////////////////
std::function<void(bool)> data[100];
// data=test_func(?,s3); // error
data[0]=[](bool b){test_func(b,s3);}; // ok
data[0](true);
return 0;
}
If you want to avoid a lambda function completely as well as templates you can use a functional (class with operator()):
typedef void (&F)(void);
class TestFunc {
F f;
public:
TestFunc(const F f) : f(f) {}
void operator()(bool B) const {
if(B) f();
}
};
Assign it with TestFunc(s3). Just typedef F to the function type, no need for a template:
typedef void (&F)(void);
and remove the template completely - I usually prefer less templates if possible, but that's taste. A template would only really be called for if you need different function signature support.
To use a standard library functional just change the typedef:
typedef std::function<void(void)> F;
If each s_n is a regular function with an identical signature, you can just remove that f parameter from test_func and instead pass the function itself as template parameter.
template<void(&f)()>
void test_func(bool b)
{
if(b)
f();
}
And use like this:
data[0] = test_func<s1>;
Function pointers and references are explicitly allowed as template non-type parameters by [temp.param/4]:
A non-type template-parameter shall have one of the following
(optionally cv-qualified) types:
[...]
pointer to object or pointer to function,
lvalue reference to object or lvalue reference to function,
You could create your lambda in a helper function:
#include <iostream>
#include <string>
#include <functional>
#include <vector>
template<typename F>
void test_func(bool b,F f) {
if(b) {
f();
}
}
std::function<void(bool)> wrap_function(const std::function<void(void)> &f) {
return [f](bool b){test_func(b,f);};
}
void s1() {
std::cout<<"s1 \n";
}
int main() {
std::vector<std::function<void(bool)>> data;
data.push_back(wrap_function(s1));
data[0](true);
}
And you should use std::vector, std::array or another std container instead of std::function<void(bool)> data[100]
I have to store arguments (parameter pack), and pass the arguments to another function.
As a result, I cannot use lambda. And a good choice is std::bind.
But for this code
struct A{};
void test(A &&){}
int main()
{
A a;
test(move(a)); //work
bind(test,a)(); //compile fail; copy a to std::bind, pass a to test
}
According to standard, all variables stored in std::bind will be pass as lvalue to function. (The C++ standard doesn't say that, by I think that is what it means.)
And that means I cannot use a function (has rvalue reference in parameter) with std::bind.
One solution is to change test(A &&) to test(A &), but this only works for your project (and make it strange while you not only need to call test by std::thread but also need to call test by plain sequential call).
So, is there any ways to solve this problem?
You can create wrapper which will be convertible to the rvalue reference (like reference_wrapper/l-value references) and use it with bind:
It cal look like that:
#include <iostream>
#include <functional>
struct A{};
void test(A &&){ std::cout << "Works!\n"; }
template <typename T>
struct rvalue_holder
{
T value;
explicit rvalue_holder(T&& arg): value(arg) {}
operator T&&()
{
return std::move(value);
}
};
template <typename T>
rvalue_holder<T> rval(T && val)
{
return rvalue_holder<T>(std::move(val));
}
int main()
{
A a;
test(std::move(a)); //work
auto foo = std::bind(test, rval(std::move(a))); //works
foo();
}
http://coliru.stacked-crooked.com/a/56220bc89a32c860
Note: both rvalue_holder and especially rval need further work to ensure efficiency, robustness and desired behavior in all cases.
I've recently encountered code that looks like this
template <typename T>
void Foo()
{
T::Bar();
}
I'm confused, how does that compile? There's no constraint on T like in C# generics.
I realize templates are not like generics in that the former are basically glorified macros, so is the case simply that each usage of Foo is compiled against the T provided in that instance, and given that it has a Bar() function it works? Kind of like duck typing?
Is this how it worked since c++03 or is this something new in c++11?
This template function only impose that when substituing the type T, the expression T::Bar(); is valid, as long as it is valid, it will compile (there is no C#-like constraints in C++) :
Here are two examples using your template:
#include <iostream>
#include <functional>
struct X
{
static void Bar() { std::cout << "Bar X\n!"; }
};
struct Y
{
static std::function<void(void)> Bar;
};
std::function<void(void)> Y::Bar = []() { std::cout << "Bar Y!"; };
template <typename T>
void Foo()
{
T::Bar();
}
int main()
{
Foo<X>();
Foo<Y>();
return 0;
}
This is how templates work and have worked always, nothing new here in C++11. It compiles if T::Bar() is valid for a given type, so it is duck typing as you said. Most of the C++ standard library works based on this principle - e.g. an iterator needs the operator* to work, and if you have your own iterators they will work with standard algorithms provided you implement this operator (and other operations required based on the iterator category). You do not need to specify your iterator in any other way - just provide the required operations.
Templates are only compiled when you instantiate them, i.e. by doing
Foo<int>();
In that case the actual code is generated by substituting T for the concrete type that you passed in (which will of course lead to a compile error here since int has no static member function Bar).
This is by design and has always been around.
What is compile-time polymorphism and why does it only apply to functions?
Way back when, "compile time polymorphism" meant function overloading. It applies only to functions because they're all you can overload.
In current C++, templates change that. Neil Butterworth has already given one example. Another uses template specialization. For example:
#include <iostream>
#include <string>
template <class T>
struct my_template {
T foo;
my_template() : foo(T()) {}
};
template <>
struct my_template<int> {
enum { foo = 42 };
};
int main() {
my_template<int> x;
my_template<long> y;
my_template<std::string> z;
std::cout << x.foo << "\n";
std::cout << y.foo << "\n";
std::cout << "\"" << z.foo << "\"";
return 0;
}
This should yield 42, 0, and "" (an empty string) -- we're getting a struct that acts differently for each type.
Here we have "compile time polymorphism" of classes instead of functions. I suppose if you wanted to argue the point, you could claim that this is at least partially the result of the constructor (a function) in at least one case, but the specialized version of my_template doesn't even have a constructor.
Edit: As to why this is polymorphism. I put "compile time polymorphism" in quotes for a reason -- it's somewhat different from normal polymorphism. Nonetheless, we're getting an effect similar to what we'd expect from overloading functions:
int value(int x) { return 0; }
long value(long x) { return 42; }
std::cout << value(1);
std::cout << value(1L);
Function overloading and specialization are giving similar effects. I agree that it's open to some question whether "polymorphism" applies to either, but I think it applies about equally well to one as the other.
With compile time polymorphism one usually means the fact that you can have a several functions with the same name and the compiler will choose at compile time which one to used depending on the arguments:
void foo(int x);
void foo(float y);
//Somewhere else
int x = 3;
foo(x); //Will call first function
float y = 2;
foo(y); //Will call second function
The function foo is said to be overloaded. Various types of template instantiation could also be called compile time polymorphism.
Compile time polymorphism is a term that refers to C++ template programming. For example, at compile time you determine the actual type of a std::vector by what it contains:
std::vector <int> vi;
std::vector <std::string> vs;
I'm not sure why you think it it is limited to functions.
The thing which only applies to functions is template parameter deduction. If I have a function template:
template <typename T>
void foo(T &t);
Then I can do int a = 0; foo(a);, and this will be equivalent to int a = 0; foo<int>(a);. The compiler works out that I mean foo<int>. At least, it works out that it should use foo<int> - if that's not what I meant then bad luck to me, and I could have written foo<unsigned int>(a); or whatever.
However, if I have a class template:
template <typename T>
struct Foo {
T &t;
Foo(T &t) : t(t) {}
T &getT() { return t; }
};
Then I can't do int a = 0; Foo(a).getT();. I have to specify Foo<int>(a). The compiler isn't allowed to work out that I mean Foo<int>.
So you might say that class templates are "less polymorphic" than function templates. Polymorphism usually means that you don't have to write code to make the type of your object explicit. Function templates allow that (in this particular case), and class templates don't.
As for why this is the case - the standard says so, I don't know why. The usual suspects are (a) it's too difficult to implement, (b) it's not useful, in the opinion of the standard committee, or (c) it creates some contradiction or ambiguity somewhere else in the language.
But you can still do other kinds of polymorphism with classes:
template <typename T>
struct Foo {
T &t;
Foo(T &t): t(t) {}
void handleMany(int *ra, size_t s) {
for (size_t i = 0; i < s; ++i) {
t.handleOne(ra[i]);
}
}
};
This is usually also called compile-time polymorphism, because as far as the author of the template is concerned, t.handleOne could be anything, and what it is will be resolved when necessary, "later" in the compilation when Foo is instantiated.
Compile time polymorphism applies to functions and operator overloads.
Read this http://cpp-tutorial.cpp4u.com/OOP_polymorphism.html