I have a problem with ambiguity in the following code while using the apply function. It is based on the stackoverflow question here.
1) I have a helper class, because templated functions as pointers are not allowed:
template<typename TT, class...Ts>
struct selector_helper
{
static TT doSelect(Ts&&... params)
{
return iSelectable<Ts...>::select<TT>(std::forward<Ts>(params)...);
}
};
I tried to run the apply function, but run into problems. I tried following two codes but no one with success:
2.1) error: apply: none of the 2 overloads could convert all the argument types
boost::tuple<Ts...> tpl;
return apply<T, Ts...>(selector_helper<T, Ts...>::doSelect, tpl);
2.2) here I get two errors:
- Error 2 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),boost::tuples::tuple &&)' : template parameter 'Args' is ambiguous
Error 3 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),const boost::tuples::tuple &)' : template parameter 'Args' is ambiguous
boost::tuple<Ts...> tpl; return apply(selector_helper<T, Ts...>::doSelect, tpl);
edit: more explanation:
Both examples are runned within select method, which is in a class:
class database
{
template<typename T, typename...Ts>
T select_(const std::string& sql)
{
// apply examples
}
};
And called here:
database db;
User result = db.select_<User, int, std::string, std::string>
("select id, email, name from credentials_tbl limit 1");
What did I miss?
here is a full example, I hope it contains everything: (when running with Microsoft Visual Studio 2013 I get the same errors)
// apply_test.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <boost/noncopyable.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/tuple/tuple.hpp>
using namespace boost;
/* apply methods from https://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments#answer-6454211 */
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------UNPACK TUPLE AND APPLY TO FUNCTION ---------
template<class Ret, class... Args, int... Indexes >
Ret apply_helper(Ret(*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup)
{
return pf(forward<Args>(get<Indexes>(tup))...);
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), const tuple<Args...>& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(),
tuple<Args...>(tup));
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), tuple<Args...>&& tup)
{
return apply_helper<Ret, Args...>(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup));
}
/* end of apply methods */
/* class iSelectable */
template <typename...> struct iSelectable;
template<class...Ts>
class iSelectable
{
public:
template<typename T>
static T select(Ts&&...params)
{
return T(std::forward<Ts>(params)...);
}
};
/* selector_helper */
template<typename TT, class...Ts>
struct selector_helper
{
static TT doSelect(Ts&&... params)
{
return iSelectable<Ts...>::select<TT>(std::forward<Ts>(params)...);
}
};
class postgres_database_impl : private boost::noncopyable
, public boost::enable_shared_from_this<postgres_database_impl>
{
public:
template<typename T, typename...Ts>
T select_(const std::string& sql)
{
boost::tuple<Ts...> tpl;
/* This is where my errors occur: */
return apply(selector_helper<T, Ts...>::doSelect, tpl);
}
};
typedef boost::shared_ptr<postgres_database_impl> DatabaseImpl;
class Database : private boost::noncopyable
{
public:
template<typename T, typename...Ts>
T select_(const std::string& sql)
{
return impl_->select_<T, Ts...>(sql);
}
private:
DatabaseImpl impl_;
};
class User : public iSelectable < int, std::string, std::string >
{
public:
User(int id, const std::string& name, const std::string& surname)
{
/* only for testing purposes */
std::cout << name << ", ";
std::cout << name << ", ";
std::cout << surname << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Database db;
User result = db.select_<User, int, std::string, std::string>
("select id, email, name from credentials_tbl limit 1");
return 0;
}