I am writing a sorting library with sorter function objects. One of the main classes, sorter_facade, is intended to provide some overloads of operator() to the sorter depending on the overloads that already exist. Here is a simple reduced example of a heap_sorter object, implementing a heapsort:
struct heap_sorter:
sorter_facade<heap_sorter>
{
using sorter_facade<heap_sorter>::operator();
template<typename Iterator>
auto operator()(Iterator first, Iterator last) const
-> void
{
std::make_heap(first, last);
std::sort_heap(first, last);
}
};
One of the simplest goals of sorter_facade is to provide an iterable overload to the sorter's operator() when an overload taking a pair of iterators already exists. Here is a reduced implementation of sorter_facade, sufficient for the problem at hand:
template<typename Sorter>
struct sorter_facade
{
template<typename Iterable>
auto operator()(Iterable& iterable) const
-> std::enable_if_t<
not has_sort<Sorter, Iterable>,
decltype(std::declval<Sorter&>()(std::begin(iterable), std::end(iterable)))
>
{
return Sorter{}(std::begin(iterable), std::end(iterable));
}
};
In this class, has_sort is a trait used to detect whether a sorter has an operator() overload taking an Iterable&. It is implemented using a hand-rolled version of the detection idiom:
template<typename Sorter, typename Iterable>
using has_sort_t = std::result_of_t<Sorter(Iterable&)>;
template<typename Sorter, typename Iterable>
constexpr bool has_sort = std::experimental::is_detected_v<has_sort_t, Sorter, Iterable>;
Now, to the actual problem: the following main works well with g++ 5.2:
int main()
{
std::vector<int> vec(3);
heap_sorter{}(vec);
}
However, it fails with clang++ 3.7.0, with the following error message:
main.cpp:87:5: error: no matching function for call to object of type 'heap_sorter'
heap_sorter{}(vec);
^~~~~~~~~~~~~
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/type_traits:2388:44: note: candidate template ignored: disabled by 'enable_if' [with Iterable = std::vector<int, std::allocator<int> >]
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^
main.cpp:75:10: note: candidate function template not viable: requires 2 arguments, but 1 was provided
auto operator()(Iterator first, Iterator last) const
^
1 error generated.
Apparently, when evaluating the std::enable_if_t, it seems to consider that Sorter already has an operator() able to take an Iterable&, which probably means that clang++ and g++ do not valuate the "same" Sorter when checking for the existence of the overload.
For this simple example, removing the std::enable_if_t makes the whole thing work, but the class sorter_facade is actually much bigger than that and I need it to resolve ambiguity problems with other overloads of operator(), so just removing it isn't a solution.
So... what causes the error? Should compilers accept or reject this code? Finally, is there a standard-compatible way to make this work with the latest versions of g++ and clang++?
EDIT: as a side note, I managed to get all the crazy to work with both g++5 and clang++3.8 by adding another layer of black magic to the point I've no idea why it even works anymore at all. While of all the previous questions hold, here is the « workaround » (using C++17 std::void_t):
tempate<typename Sorter>
struct wrapper:
Sorter
{
#ifdef __clang__
using Sorter::operator();
template<typename Iterable>
auto operator()(Iterable& iterable) const
-> std::enable_if_t<false, std::void_t<Iterable>>
{}
#endif
};
template<typename Sorter>
struct sorter_facade
{
template<typename Iterable>
auto operator()(Iterable& iterable) const
-> std::enable_if_t<
not has_sort<wrapper<Sorter>, Iterable>,
decltype(std::declval<Sorter&>()(std::begin(iterable), std::end(iterable)))
>
{
return Sorter{}(std::begin(iterable), std::end(iterable));
}
};
I guess that it abuses different compiler-specific behaviours in both g++ and clang++ and achieves something that wasn't meant to work, but still... I'm amazed that it works, even in my whole project, which has many more tricky things to handle...
I am pretty sure this is a bug in clang. The return type of sorter_facade<Sorter>::operator() depends on the template argument Iterator. Still, the compiler seems to decide to SFINAE out before knowing the arguments.
But bug or not, you can work around this by explicitly deferring the calculation of the return type. Here is a version that does not depend on black magic. Works with gcc-5.2 and clang-3.6:
template<typename Sorter, typename Iterable>
struct sort_result
{
using type = decltype(
std::declval<Sorter&>()(
std::begin(std::declval<Iterable&>()),
std::end(std::declval<Iterable&>())));
};
template<typename Sorter, typename Deferred>
using sort_result_t = typename sort_result<Sorter, Deferred>::type;
template<typename Sorter>
struct sorter_facade
{
template <typename Iterable>
auto operator()(Iterable& iterable) const
-> sort_result_t<Sorter, Iterable>
{
return Sorter{}(std::begin(iterable), std::end(iterable));
}
};
struct heap_sorter:
sorter_facade<heap_sorter>
{
using sorter_facade<heap_sorter>::operator();
template<typename Iterator>
auto operator()(Iterator first, Iterator last) const
-> void
{
std::make_heap(first, last);
std::sort_heap(first, last);
}
};
int main()
{
std::vector<int> vec(3);
heap_sorter{}(vec);
}
The trick is: The compiler does not know if you specialize the result_type later on. Therefore it has to wait until you actually use it, before trying to determine the return type.
Related
I want to write a class that takes a pair of iterators as parameters to the constructor, but I dont know how to raise an error at compile-time when those iterators' value_type doesn't match an expected type. This is what I tried using typeid:
#include <vector>
struct foo {
std::vector<double> data;
template <typename IT>
foo(IT begin, IT end){
typedef int static_assert_valuetype_is_double[
typeid(typename IT::value_type) == typeid(double) ? 1 : -1
];
std::cout << "constructor called \n";
data = std::vector<double>(begin,end);
}
};
int main()
{
std::vector<double> x(5);
foo f(x.begin(),x.end()); // double: ok
std::vector<int> y(10);
foo g(y.begin(),y.end()); // int: should not compile
}
Note that in this case, int to double would be fine, but thats just an example and in the real code the types have to match exactly. To my surprise in both cases, the constructor works without errors (there is only a warning about the unused typedef). Does the -1 sized array static assert trick not work when the typedef is declared inside a method? How do I produce an error when IT::value_type is the wrong type?
PS: would be nice if there was an easy C++98 solution, but if this gets too complicated, I could also accept a C++11 solution.
In modern C++, you could have used std::is_same and static_assert:
static_assert(std::is_same_v<typename std::iterator_traits<IT>::value_type, double>,
"wrong iterator");
See also std::iterator_traits: an iterator it is not guaranteed to have a value_type typedef, and one should use std::iterator_traits<it>::value_type instead.
In C++ 98, is_same is trivial to implement, static_assert needs a negative-size array trick or the BOOST_STATIC_ASSERT.
For a solution that works in C++98 and later.....
#include <iterator>
template<class T> struct TypeChecker
{};
template<> struct TypeChecker<double>
{
typedef double valid_type;
};
template <typename IT>
void foo(IT begin, IT end)
{
typename TypeChecker<typename std::iterator_traits<IT>::value_type>::valid_type type_checker;
(void)type_checker;
// whatever
}
Instantiations of foo() will succeed for any for an iterator for which value_type is double, and fail to compile otherwise.
The premise is that TypeChecker<x> does not have a valid_type for any x other than double, but we attempt to instantiate an instance of that type in foo(). The (void)type_checker prevents warnings, from some compilers about a variable that is never used, for valid types.
Here is a C++98 compliant way to implement it.....
First the fun part: Implementing a is_same is rather straightforward
template <typename T,typename U> struct is_same_type { static const bool value; };
template <typename T,typename U> const bool is_same_type<T,U>::value = false;
template <typename T> struct is_same_type<T,T> { static const bool value; };
template <typename T> const bool is_same_type<T,T>::value = true;
Now the not-so-fun part (C++11 really helps to statically assert without causing coworkers raising some eyebrows):
struct foo {
std::vector<double> data;
template <typename IT>
foo(IT begin, IT end) : data(begin,end) {
typedef int static_assert_valuetype_is_double[
is_same_type<double,typename IT::value_type>::value ? 1 : -1
];
std::cout << "constructor called \n";
}
};
int main(){
std::vector<double> x(5,2.3);
foo f(x.begin(),x.end());
for (std::vector<double>::iterator it = f.data.begin(); it != f.data.end();++it) std::cout << *it << " ";
//std::vector<int> y(10,3);
//foo g(y.begin(),y.end()); // THIS FAILS (AS EXPECTED)
}
As pointed out by others, I should actually be using std::iterator_traits<IT>::value_type as not every iterator has a value_type. However, in my case I rather want to restrict the possible iterators to a small set and disallowing iterators without a value_type isnt a problem in my specific case.
Also note that the code in the question assigned to the member, while it is of course better to use the initializer list.
The following code implements a hash function for a std::tuple which is then used in a different segment of my code-base in a std::unordered_map of std::tuples.
// compute hash function recursively through each std::tuple element
template<class Tuple, std::size_t N>
struct tuple_hash_compute {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<N-1, decltype(t)>::type; // OFFENDING LINE
return tuple_hash_compute<Tuple, N-1>::hash_compute(t)
+ std::hash<type>()(std::get<N-1>(t));
}
};
// base helper
template<class Tuple>
struct tuple_hash_compute<Tuple, 1> {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<0, decltype(t)>::type; // OFFENDING LINE
return 51U + std::hash<type>()(std::get<0>(t))*51U;
}
};
// tuple_hash function object
struct tuple_hash {
template<class... Args>
std::size_t operator()(const std::tuple<Args...>& t) const {
return tuple_hash_compute<decltype(t), sizeof...(Args)>::hash_compute(t);
}
// will use std::unordered_map of std::pair too, so overload reqd
template<class Ty1, class Ty2>
std::size_t operator()(const std::pair<Ty1, Ty2>& p) const {
return tuple_hash_compute<decltype(t), 2>::hash_compute(p);
}
};
Then, just as an example, I would use this hash function-object like so,
std::unordered_map<std::tuple<int,int,int>, std::size_t, tuple_hash> agg_map;
agg_map.insert(std::make_pair(std::make_tuple(1,2,3), 0U));
agg_map.insert(std::make_pair(std::make_tuple(4,5,6), 1U));
However, in both GCC 6.1.0 and MSVC2015, I receive the following errors (both the same for each offending line above):
error: invalid use of incomplete type 'class std::tuple_element<2ul, const std::tuple<int,int,int>&>'
I'm not entirely sure what's causing this error (though it may be due to "abstraction" of passing the std::tuple via the template parameter Tuple) or how it can be solved so any help is appreciated.
For a parameter declared as below:
const Tuple& t
decltype(t) yields:
const Tuple&
Similarly, for a parameter declared as:
const std::pair<Ty1, Ty2>& t
decltype(t) yields:
const std::pair<Ty1, Ty2>&
In both cases, the produced type is a reference to a tuple-like type. However, std::tuple_element is not specialized for references, which means, the compiler falls back to the primary, undefined class template:
template <size_t I, typename T> class tuple_element;
What you want, is a plain Tuple in the former case, and std::pair<Ty1, Ty2> in the latter case.
If you have this problem with a type Tuple that may or may not be a reference, you can use std::remove_reference like so:
typename std::tuple_element<num, typename std::remove_reference<Tuple>::type>::type
or, for C++17,
std::tuple_element_t<num, std::remove_reference_t<Tuple>>
PS: I don't think it works with std::reference_wrapper though...
I want to make a function that takes a lambda as parameter, and returns an object which type depends on the lambda function return type.
What I'm trying to achieve is essentially no explicit template parameter at instantiation.
For now, here is my solution, and my question is: is there a shorter (and more elegant) way to do it ?
template<typename Func, typename RT = std::unordered_map<int,
decltype(((Func*)nullptr)->operator()(T())) > >
RT mapResult(Func func)
{
RT r;
for (auto &i : mData)
r.insert({i.first, func(mData.second)});
return r;
}
To make it a little more clear, the lambda type Func takes T& as parameter and returns a vector of a certain type, and mapResult maps the result of func in an unordered_map whose _Ty template parameter is the lambda function return type (potentially something else, but still dependent on this type). The actual code is much more complicated, but I'm trying to gain clarity on this point specifically.
The only solution I found to avoid writing the RT type several times was to put it in the template parameters list and give it a default value, dependent on the first template parameter (which itself is deduced from the function argument). It's a little like defining a templated typename.
I'm using VC12, but want to have portable code that compiles under g++ as well.
The instantiation then looks like this (dummy example):
auto r = c.mapResult([](T &t){return std::vector<int> {(int)t.size()};});
The C++11 Standard Library contains a metafunction called result_of. This metafunction computes the return type of a function object. Probably due to its history in boost (and C++03), it is used in a rather peculiar way: You pass it the type of the function object and the type of the arguments you want to call the function object with via a combined function type. For example:
struct my_function_object
{
bool operator()(int);
char operator()(double);
};
std::result_of<my_function_object(int)>::type // yields bool
std::result_of<my_function_object(short)>::type // yields bool
std::result_of<my_function_object(double)>::type // yields char
result_of performs overload resolution. If you call short s{}; my_function_object{}(s);, overload resolution will select my_function_object::operator()(int). Therefore, the corresponding result_of<my_function_object(short)>::type yields bool.
Using this trait, you can simplify the computation of the return type as follows:
template<typename Func, typename RT = std::unordered_map<int,
typename std::result_of<Func(T&)>::type > >
RT mapResult(Func func)
{
RT r;
for (auto &i : mData)
r.insert({i.first, func(i.second)});
return r;
}
The T& parameter tells result_of to use an lvalue argument in overload resolution. The default (for a non-reference type T) is xvalue (T&&).
There is one slight difference to the OP's version: SFINAE will probably not work correctly using std::result_of (in C++11). This was resolved in C++14. See N3462.
C++14 has introduced standardized alias templates like result_of_t so you can get rid of the typename and ::type:
template<typename Func, typename RT = std::unordered_map<int,
std::result_of_t<Func(T&)> > >
RT mapResult(Func func)
{
RT r;
for (auto &i : mData)
r.insert({i.first, func(i.second)});
return r;
}
If you're using Visual Studio 2013 or newer, you can write alias templates yourself. You could also go one step further and write the whole return type as a metafunction:
template<typename FT> using result_of_t = typename std::result_of<FT>::type;
template<typename Func> using RetType =
std::unordered_map<int, result_of_t<Func(T&)> >;
template<typename Func, typename RT = RetType<Func> >
RT mapResult(Func func)
{
RT r;
for (auto &i : mData)
r.insert({i.first, func(i.second)});
return r;
}
Of course, if you have sufficient C++14 core language support (not in VS12), you can use return type deduction as well:
template<typename Func>
auto mapResult(Func func)
{
auto r = std::unordered_map<int, result_of_t<Func(T&)>>{};
for (auto &i : mData)
r.insert({i.first, func(i.second)});
return r;
}
It is also possible to shorten a version using decltype:
using std::declval;
decltype(declval<Func>(T{}))
although this isn't quite correct, both the function object and the argument will be an lvalue:
decltype(declval<Func&>(declval<T&>{}))
declval will use an xvalue in overload resolution for a non-reference type X. By adding the &, we tell it to use an lvalue instead. (result_of is based on declval, so both show this behaviour.)
Note that in any case, it might be useful to run the result_of_t<Func(T&)> type through the std::decay metafunction, to get rid e.g. of references which appear in cases such as:
[](string const& s) -> string const& { return s; } // identity
This does depend on your use case though, and either choice should be documented.
IIRC, emplace is slightly more efficient (in theory) in this situation (inserting unique elements):
r.emplace(i.first, func(i.second));
It might be possible to further optimize this function, e.g. by reserving a bucket count before the insertion, or maybe with an iterator adapter to leverage the constructor for insertion. Using std::transform should also be possible, though I'd guess it cannot be as efficient due to additional moves of the value_type pair.
In C++11 there are few things that you can do to make it sorter. One way is to use template aliases:
namespace details
{
template <typename Func>
using map_type_t =
std::unordered_map<int, typename std::result_of<Func(T)>::type>>;
}
template <typename Func>
details::map_type_t<Func> mapResult(Func func)
{
details::map_type_t<Func> r;
//...
return r;
}
In C++14 you can leave the return type deduction to the compiler:
template <typename Func>
auto mapResult(Func func)
{
std::unordered_map<int, decltype(func(T()))> r;
//...
return r;
}
In my C++ code which depends heavily on template metaprogramming I have something like that:
template <int TFoo, int TBar, int TBaz, int TQux, typename TSpam>
struct MyClassConfig {
static int const Foo = TFoo;
static int const Bar = TBar;
static int const Baz = TBaz;
static int const Qux = TQux;
using Spam = TSpam;
};
template <typename Config>
class MyClass {
...
};
That is, I use dummy classes to contain various parameters. Here, there's usually a lot of nesting, so MyClassConfig::Spam could again be such a configuration class.
This all works until the compiler (g++) decides it doesn't like my code. At this point it will happily print out the entire MyClassConfig at any chance it gets. Combined with other forms of metaprogramming used, the error messages then explode into megabytes.
EDIT To make it more clear what's happening, see my actual code and a typical error output. The first link points to my giant configuration type aliased as PrinterParams which is then given as a template parameter to PrinterMain<>. See how the error output is 99% composed of this configuration type being blown out in its full glory. I believe the error would be much more readable if only the PrinterParams would be kept in alias form instead of being expanded by the compiler.
Use the newest version of GCC you can get. The GCC guys improved their error messages a lot. Especially 4.8 formatted them better and the future 4.9 added color to it. Looking back I am wondering how I could ever use GCC 4.4 or older.
If you can switch to clang, they have superior error messages. Clang is a major driving force for GCC to improve the error messages.
But in your case I think Robert Harvey is right. Your example looks like template abuse.
Thank you for calling C++ Standard Committee. Due to unusually heavy call volume, we are experiencing longer-than-normal delays in answering your call. We apologize for this inconvenience. Your call is important for us. Please stay on the line.
(Funny hat off)
The exploding error messages problem was, and still is, a major bane of C++ library writers and users. There's no satisfactory solution. Concepts were slated to be the solution in C++11, but concepts were scraped at the last minute. Concepts Lite may or may not enter C++1y. As of now (C+11), library writers are left with static_assert, but this requires thoughtful application by hand. Manual labour, boo! To use static_assert, you, the library writer, do the following:
Write down all requirements that template arguments must satisfy.
For each requirement, create a boolean-valued compile-time function (constexpr or plain old type<arg>::value) that is true when the requirement is satisfied.
Use all these functions in static_assert declarations in each template instantiateable by the user.
Apply these procedures religiously, and you just might have a chance of producing readable error messages that do not explode to megabytes.
Below is a hastily thrown together example of how this could be done. Compile it with g++ and see what happens. Only remember that it's not ready for production ;) No attempt has been made to deal with references, rvalue references, and const. Note that clang++ reports static_assert and all the other errors it finds in a function, which sort of defeats its purpose; while g++ reports only static_asserts. So for clang++ we additionally need to suppress the function body if any of the static asserts has fired; this is left as an exercise for the reader.
#include <vector>
#include <algorithm>
#include <type_traits>
#include <utility>
template <class T> struct supports_inequal
{
template <class U> static auto test(const U u) -> decltype(bool(u != u), char(0)) { }
static std::array<char, 2> test(...) { }
static const bool value = (sizeof(test(std::declval<T>())) == 1);
};
template <class T> struct supports_dereference
{
template <class U> static auto test(const U u) -> decltype(*u, char(0)) { }
static std::array<char, 2> test(...) { }
static const bool value = (sizeof(test(std::declval<T>())) == 1);
};
template <class T> struct supports_postincrement
{
template <class U> static auto test(U u) -> decltype(u++, char(0)) { }
static std::array<char, 2> test(...) { }
static const bool value = (sizeof(test(std::declval<T>())) == 1);
};
template <class T1, class T2> struct supports_assignment
{
template <class U, class V> static auto postincrement_test(U u, const V v) -> decltype(*u = *v, char(0)) { }
static std::array<char, 2> test(...) { }
static const bool value = (sizeof(test(std::declval<T1>(),std::declval<T2>())) == 1);
};
template <typename It1, typename It2, typename It3>
void my_copy (It1 it1, It2 it2, It3 it3)
{
// Check that It1 and It2 are the same type
static_assert (std::is_same<It1, It2>::value, "\n\n\nArgument 1 and argument 2 of my_copy(it1, it2, it3) must be of the same type\n\n\n");
static const bool previous_assertions_1 = std::is_same<It1, It2>::value;
static_assert (!previous_assertions_1 || supports_inequal<It1>::value, "\n\n\nArgument 1 and argument 2 of my_copy(it1, it2, it3) must be comparable with '!='\n\n\n");
static const bool previous_assertions_2 = previous_assertions_1 && supports_inequal<It1>::value;
static_assert (!previous_assertions_2 || supports_dereference<It1>::value, "\n\n\nArguments 1 and 2 of my_copy(it1, it2, it3) must be dereferenceable\n\n\n");
static const bool previous_assertions_3 = previous_assertions_2 && supports_dereference<It1>::value;
static_assert (!previous_assertions_3 || supports_dereference<It3>::value, "\n\n\nArgument 3 of my_copy(it1, it2, it3) must be dereferenceable\n\n\n");
static const bool previous_assertions_4 = previous_assertions_3 && supports_dereference<It3>::value;
static_assert (!previous_assertions_4 || supports_postincrement<It1>::value, "\n\n\nArguments 1 and 2 of my_copy(it1, it2, it3) must be postincrementable\n\n\n");
static const bool previous_assertions_5 = previous_assertions_4 && supports_postincrement<It1>::value;
static_assert (!previous_assertions_5 || supports_dereference<It3>::value, "\n\n\nArgument 3 and of my_copy(it1, it2, it3) must be postincrementable\n\n\n");
static const bool previous_assertions_6 = previous_assertions_4 && supports_postincrement<It3>::value;
std::copy (it1, it2, it3); // g++ does not complain here when static_assert fires, clang++ does (QoI issue": we have staic assert so that we could control the error messages!)
}
struct A {};
int main ()
{
int *a, *b, *c;
my_copy(a, b, c); // no error
std::copy(a, b, c); // no error
my_copy(a, b, A()); // human readable error message: argument 3 of my_copy(it1, it2, it3) must be dereferenceable
std::copy(a, b, A()); // stack of incomprehensible error messages : "\n\n\nerror: no type named ‘value_type’ in ‘struct std::iterator_traits<A>’"?
}
The easier solution is to use meta-functions:
template <int TFoo, int TBar, int TBaz, int TQux, typename TSpam>
struct MyClassConfig { };
template <int TFoo, int TBar, int TBaz, int TQux, typename TSpam>
constexpr int FooOf(MyClassConfig<TFoo, TBar, TBaz, TQux, TSpam>) {
return TFoo;
};
using currentConfig = MyClassConfig<1,2,3,4, float>;
const int currentFoo = FooOf(currentConfig()); // = 1
Because FooOf isn't a member of MyClassConfig, that class stays a lot smaller.
I'm trying to use Boost::Fusion to transform a list of function's parameter types into a fusion::list. Ultimately, I am trying to turn a list of variables into parameters that I can call a function with (http://stackoverflow.com/questions/11164914/generating-wrappings-for-c-functions).
I've gotten this to work for non-referenced variables. However, it fails to compile for non-referenced variables when I try to turn the function's parameter list (specifically on the fusion::to_list it complains it can't deref the iterator).
I've simplified the code down by a bit below:
struct identity {
template<typename Sig> struct result;
template <typename T>
struct result<convert(T)> { typedef T type; };
template <typename T>
typename T operator ()(T) const {
return T();
}
};
int main(int argc, char **argv) {
typedef BOOST_TYPEOF(foo) params_type;
auto seq = function_types::parameter_types<params_type>();
auto transformed = fusion::transform(seq, identity());
auto passedParams = fusion::as_list(transformed);
}
If foo is defined as:
int foo(int a) { return 5*a; }
it works fine, but it breaks on:
int foo(int &a) { return 5*a; }
For the purposes of my code, I don't actually need the references kept in the sequence, which I am assuming is the issue (also, searches I've done tend to point that as being the culprit). However, I'm not completely sure of how to strip the transformed function of these references before as_list is called.
I tried something along the lines of:
template <typename T>
struct result<convert(T)>: remove_reference<T> {};
template <typename T>
typename remove_reference<T>::type operator ()(remove_reference<T>::type) const { return typename remove_reference<T>::type(); }
but got the same compile errors.
Any ideas of how to fix this?
update
Here is the truncated compiler error I get (with clang++ --std=c++0x) for both cases given above:
/usr/local/include/boost/fusion/adapted/mpl/mpl_iterator.hpp:43:24: error:
reference to type 'int' requires an initializer
return type();
^
/usr/local/include/boost/fusion/iterator/deref.hpp:61:28: note: in instantiation
of member function
'boost::fusion::mpl_iterator<boost::mpl::v_iter<boost::function_types::parameter_types<void
(int &), boost::add_reference<mpl_::arg<-1> > >, 0>
>::deref<boost::fusion::mpl_iterator<boost::mpl::v_iter<boost::function_types::parameter_types<void
(int &), boost::add_reference<mpl_::arg<-1> > >, 0> > >::call' requested
here
return deref_meta::call(i);
...
test4.cpp:65:22: note: in instantiation of function template specialization
'boost::fusion::as_list<boost::fusion::transform_view<const
boost::function_types::parameter_types<void (int &),
boost::add_reference<mpl_::arg<-1> > >, convert, boost::fusion::void_> >'
requested here
auto passedParams = fusion::as_list(transformed);
If your compiler is C++11 compatible, you might want to look into the `std::remove_reference function. Or at least try to find an implementation of it and use as reference for making your own.