Boost mpl for each and free functions - c++

Why this code does not compile:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <iostream>
using namespace std;
using namespace boost;
template <class T> // specific visitor for type printing
static void print_type(T t)
{
std::cout << typeid(T).name() << std::endl;
}
typedef mpl::vector<int, long, char*> s;
int main ()
{
mpl::for_each<s>(print_type());
}
I wonder - how to make boost mpl for_each work with free functions from same class?

As stated you need a functor.
The code below includes an additional wrap template that allows the print functor to cope with references.
#include <iostream>
#include <typeinfo>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/placeholders.hpp>
using namespace std;
using namespace boost;
template <typename T>
struct wrap {};
struct print_type
{
template< typename T>
void operator()( wrap<T> ) const
{
cout << typeid(T).name() << "\n";
}
};
typedef mpl::vector<int, long&, char*> s;
int main ()
{
mpl::for_each<s, wrap<mpl::placeholders::_1> >(print_type());
return 0;
}
Note: this code based on examples in the book 'C++ Template Metaprogramming by David Abrahams and Aleksy Gurtovoy

mpl::for_each<s>(print_type());
This is wrong in a couple of ways.
First, print_type is a function that returns void. print_type() is an attempt to call that function. Since it returns nothing, you can't stick its non-existent return value into something else.
Second, print_type is a template function. You cannot call a template function without specifying the template parameters. So print_type() is ill-formed.
Third, even mpl::for_each<s>(print_type) doesn't work, because print_type is not a value (nor is it convertible to a value); it is a template. You cannot pass a template as the argument of a function. That's why visitors (for many things, not just MPL) are objects, which can have template operator() members.

Related

Pass template function to std::bind?

I want to use std::bind with template function. Is it somehow possible?
P.S. It is IMPORTANT to use std::bind, because I know at least one solution through lambdas and want to find out if there is std::bind solution.
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
struct foo : std::enable_shared_from_this<foo>
{
void f()
{
// doesn't compile, error : no matching function for call to 'bind'
auto cb = std::bind(&foo::handle, shared_from_this(), placeholders::_1, placeholders::_2);
}
template <typename T, typename U>
void handle(T, U)
{
}
};
int main()
{
return 0;
}
handle is not a template function. There are no "template functions". handle is a function template, ie it is a template, it is not a function. You cannot std::bind to a template. You can only std::bind to a callable.
The trick is to defer instantiation of the template and deduction of the template parameters to when the function is actually called:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
struct foo {
struct handle_caller {
template <typename T,typename U>
void operator()(foo* f, T t,U u){
f->handle(t,u);
}
};
void f()
{
auto cb = std::bind(handle_caller{},this, placeholders::_1, placeholders::_2);
}
template <typename T, typename U>
void handle(T, U)
{
}
};
int main()
{
return 0;
}
The callable passed to bind is an object of a concrete type handle_caller. It is not a template. Only when cb is called the parameters are forwarded to handle_caller::operator() where the template arguments can be deduced.
Lambdas can do this out-of-the box, because a lambda with auto arguments is of a concrete type and only its operator() is a template:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
struct foo {
void f()
{
auto cb = std::bind([](auto f,auto t,auto u){ f->handle(t,u);},this, placeholders::_1, placeholders::_2);
}
template <typename T, typename U>
void handle(T, U)
{
}
};
int main()
{
return 0;
}
However, once you use the lambda there is no need for std::bind anymore, because you can bind the parameters via a lambda capture. std::bind is the ancient way to bind parameters, it is convoluted and has clunky syntax. I have read of cases that can be done with std::bind but not with a lambda, but I have never encountered one.
PS: Note that I removed the shared_from_this stuff from your code, because I know it can be used wrong easily, but I am not sure how to use it correctly. As cb is only local to foo::f there is no need to worry about the lifetime of this in the example code.
&foo::handle is not valid C++, because foo::handle is not a function. foo::handle<int, int> is a function, and foo::handle<double, std::string> is a different function.
You will have to wrap it in something, so you may as well use a lambda.

template template argument in C++

#include <vector>
#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <iostream>
#include <string>
using namespace std;
// Template-template argument must
// be a class; cannot use typename:
template<typename T, template<typename> class C>
void print2(C<T>& c) {
copy(c.begin(), c.end(),
ostream_iterator<T>(cout, " "));
cout << endl;
}
int main() {
vector<string> v(5, "Yow!");
print2(v);
} ///:~
This code looks perfect right to me. But this snippet can't compile in My Mac. The error information is the following
note: candidate template ignored: substitution failure [with T = std::__1::basic_string<char>]: template template argument has
different template parameters than its corresponding template template parameter
void print2(C<T>& c) {
^
1 error generated.
This is because std::vector is not a single-argument template. Standard mandates an element type and allocator type arguments for std::vector.
If you are not on legacy C++ and can use variadic templates, you can declare your function like this:
template<typename T, template<typename...> class C>
void print2(C<T>& c);

Get types of C++ function parameters

Is there a standard way to get the types of a function's arguments and pass around these types as a template parameter pack? I know that this is possible in C++ because it has been done before.
I was hoping that with C++14 or the upcoming C++1z, there would be an idiomatic way to implement arg_types<F>... here:
template <typename ...Params>
void some_function(); // Params = const char* and const char*
FILE* fopen(const char* restrict filename, const char* restrict mode);
int main(){
some_function<arg_types<fopen>...>();
}
Just to be clear, an answer claiming that there is no standard way to do this is not an answer. If there is no answer, I would prefer that the question remain unanswered until the solution is added to C++500 or until the heat death of the universe, whichever happens earlier :)
Edit: A deleted answer noted that I can use PRETTY_FUNCTION to get the names of parameter types. However, I want the actual types. Not the names of those types.
This syntax is slightly different.
First, because types are easier to work with than packs, a type that holds a pack. The using type=types; just saves me work in the code that generates a types:
template<class...>struct types{using type=types;};
Here is the workhorse. It takes a signature, and produces a types<?...> bundle containing the arguments for the signature. 3 steps so we can get nice clean C++14esque syntax:
template<class Sig> struct args;
template<class R, class...Args>
struct args<R(Args...)>:types<Args...>{};
template<class Sig> using args_t=typename args<Sig>::type;
Here is a syntax difference. Instead of directly taking Params..., we take a types<Params...>. This is similar to the "tag dispatching" pattern, where we exploit template function type deduction to move arguments into the type list:
template <class...Params>
void some_function(types<Params...>) {
}
My fopen is different, because I don't want to bother #includeing stuff:
void* fopen(const char* filename, const char* mode);
And the syntax is not based off of fopen, but rather the type of fopen. If you have a pointer, you'd need to do decltype(*func_ptr) or somesuch. Or we could augment the top to handle R(*)(Args...) for ease of use:
template<class Sig>
struct args<Sig*>:args<Sig>{}; // R(*)(Args...) case
template<class Sig>
struct args<Sig&>:args<Sig>{}; // R(&)(Args...) case
then test code:
int main(){
some_function(args_t<decltype(fopen)>{});
}
live example.
Note that this does not work with overloaded functions, nor does it work with function objects.
In general, this kind of thing is a bad idea, because usually you know how you are interacting with an object.
The above would only be useful if you wanted to take a function (or function pointer) and pop some arguments off some stack somewhere and call it based off the parameters it expected, or something similar.
Inspired by #Yakk, here is a slightly simplified version:
First we define helper meta function to store function argment types as tuple.
template<typename Sig>
struct signature;
template<typename R, typename ...Args>
struct signature<R(Args...)>
{
using type = std::tuple<Args...>;
};
We use concept to restrict input as function
template<typename F>
concept is_fun = std::is_function_v<F>;
Here is our function "arguments" to retrieve input's argument types. Depends on input parameter, we overload "arguments" function to accept both reference and non reference.(free function is always passed by reference. We don't even have to have function body, only return type is enough as this is meta function.
template<is_fun F>
auto arguments(const F &) -> typename signature<F>::type;
Here is testing:
void foo(const string &, int, double)
{}
static_assert(std::is_same_v<decltype (arguments(foo)),
std::tuple<const string &, int, double>>);
My full-fledged version is here which also supports lambda, functor, member function pointer
Use Boost.FunctionTypes and std::index_sequence. Below is an example which prints the argument types of the function func. You can change the doit static function to do what you want. See it in action here.
template <typename FuncType>
using Arity = boost::function_types::function_arity<FuncType>;
template <typename FuncType>
using ResultType = typename boost::function_types::result_type<FuncType>::type;
template <typename FuncType, size_t ArgIndex>
using ArgType = typename boost::mpl::at_c<boost::function_types::parameter_types<FuncType>, ArgIndex>::type;
void func(int, char, double) {}
template <typename Func, typename IndexSeq>
struct ArgPrintHelper;
template <typename Func, size_t... Inds>
struct ArgPrintHelper<Func, integer_sequence<size_t, Inds...> >
{
static void doit()
{
string typeNames[] = {typeid(ResultType<Arg>).name(), typeid(ArgType<Func, Inds>).name()...};
for (auto const& name : typeNames)
cout << name << " ";
cout << endl;
}
};
template <typename Func>
void ArgPrinter(Func f)
{
ArgPrintHelper<Func, make_index_sequence<Arity<Func>::value> >::doit();
}
int main()
{
ArgPrinter(func);
return 0;
}
Headers(moved down here to reduce noise in the above code snippet):
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/function_arity.hpp>
#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <tuple>
#include <utility>
using namespace std;
For boost users, #include <boost/type_traits.hpp>
boost::function_traits<decltype(function)>::arg1_type
boost::function_traits<decltype(function)>::arg2_type
// boost::function_traits<decltype(function)>::argN_type
using FopenArg1 = boost::function_traits<decltype(fopen)>::arg1_type;
using FopenArg2 = boost::function_traits<decltype(fopen)>::arg2_type;
void some_function(FopenArg1, FopenArg2);
Boost Document
With a C++17 (or later) conforming compiler, you can use this:
#include<iostream>
template<typename type, typename...args>
void getFuncInfo(type(*func)(args...))
{
// some code here...
// here my example:
((std::cout << typeid(args).name() << "\n"),...);
}
// every Augments you can imagines...
void someRandomFunction(int a, float b, double c, const char* d, int e[], std::pair<int, const char*> f)
{
}
// test out in main.
int main()
{
getFuncInfo(someRandomFunction);
std::cin.get();
}

boost::mpl typelist function application

I have a function that I want to perform on all the types in a typelist (currently represented by an mpl list --- is this even a reasonable way to approach it?)
The key here is that the function only cares about the type, not actual data; it calls a static function in that type to retrieve some information and then does shoves it into a hash table for later reference.
However, as far as I can tell, the mpl does not have a means of doing this --- the closest I can find is the mpl for_each operator, but it appears to want to be used on actual instantiations of each of the types, not the types themselves.
The Loki library had an "apply" function, which is more or less what I am looking for -- it got around the instantiation issue by passing a pointer to the type in the typelist as a parameter to help with deduction, but not doing a full instantiation. What should I be looking at in the MPL to get that functionality? Or am I missing something obvious?
You can use for_each "overload" with TransformOp to avoid instantiating the types:
struct functor
{
template<class T> void operator()( mpl::identity<T> )
{
std::cout << typeid(T).name() << '\n';
}
};
mpl::for_each<types, mpl::make_identity<_> >( functor() );
The easiest option just might just be this:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/for_each.hpp>
#include <typeinfo>
#include <iostream>
struct functor{
template<class T>
void operator()(T*){
std::cout << typeid(T).name() << '\n';
}
};
int main(){
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
typedef mpl::vector<char, int, float, bool> typelist;
typedef mpl::transform<typelist, boost::add_pointer<_1>>::type ptypelist;
mpl::for_each<ptypelist>(functor());
}
Do the same thing in MPL: Call boost::mpl::transform with boost::add_pointer to make a sequence of pointers to your types, and then use boost::mpl::for_each.

"templating" a namespace

I'd like to build something like this:
File 1:
template<typename Vector>
namespace myNamespace {
class myClass1{ myClass1(Vector v) {...} }
}
File 2:
template<typename Vector>
namespace myNamespace {
class myClass2{ myClass2(Vector v) {...} }
}
Of course this is not possible because you cannot template namespaces.
Instead I could use a struct instead of a namespace, but then I cannot spread the namespace functions over several files.
Is there any solution for such a problem?
PS: I know I could template the classes, but then I'd have to specify which vector type I want to use anytime I create a new class.
Following up on your comment:
Instead of writing
using namespace myNamespace<int>;
Just use templated classes and write this instead (or whatever variation):
typedef myNamespace::myClass1<int> myClass1Int;
typedef myNamespace::myClass2<int> myClass2Int;
I tend to think it's better to be explicit about what types are being used rather than trying to do something like import a particular instantiation of a namespace.
Can you more fully describe the problem that makes you think templated namespaces would be useful?
And remember you can always write a make_myClass1 free function to deduce the template type for you.
You cannot do that, but you can provide different namespaces and typedefs (not that I endorse it).
namespace template_impl {
template <typename V>
class myClass1_tmpl {...};
template <typename V>
class myClass2_tmpl {...};
}
namespace myns_Vector1 {
typedef ::template_impl::myClass1_tmpl<Vector1> myClass1;
typedef ::template_impl::myClass2_tmpl<Vector1> myClass2;
}
void foo() {
using namespace myns_Vector1;
myClass1 mc1;
}
Anyway, my classes have several template parameters.
Now I created this approach:
#include <string>
#include <iostream>
namespace myNamespace {
template<typename _integer, typename _string>
struct s {
typedef _integer integer;
typedef _string string;
};
template<class T>
class classA {
public:
static typename T::integer intFunc() { return 1; }
static typename T::string stringFunc() { return "hallo"; }
};
}
int main() {
using namespace myNamespace;
typedef s<int, std::string> types1;
typedef s<unsigned int, char*> types2;
std::cout << classA<types1>::intFunc() << std::endl;
std::cout << classA<types1>::stringFunc() << std::endl;
std::cout << classA<types2>::intFunc() << std::endl;
std::cout << classA<types2>::stringFunc() << std::endl;
}
and I think I'll combine it with Mark B's approach!
Cheers, guys!