应用中的歧义
Ambiguity within apply
我在使用 apply 函数时遇到以下代码中的歧义问题。它基于 Whosebug 问题 here.
1) 我有一个助手 class,因为模板函数作为指针是不允许的:
template<typename TT, class...Ts>
struct selector_helper
{
static TT doSelect(Ts&&... params)
{
return iSelectable<Ts...>::select<TT>(std::forward<Ts>(params)...);
}
};
我尝试运行应用函数,但是运行遇到了问题。我尝试了两个代码,但没有一个成功:
2.1) 错误:应用:2 个重载中的 none 可以转换所有参数类型
boost::tuple<Ts...> tpl;
return apply<T, Ts...>(selector_helper<T, Ts...>::doSelect, tpl);
2.2) 这里我得到两个错误:
- 错误 2 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),boost::tuples::tuple &&)' : 模板参数 'Args' 不明确
错误 3 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),const boost::tuples::tuple &)' : 模板参数 'Args' 不明确
boost::tuple<Ts...> tpl;
return apply(selector_helper<T, Ts...>::doSelect, tpl);
编辑:更多解释:
两个例子都运行内嵌在select方法中,它在class:
中
class database
{
template<typename T, typename...Ts>
T select_(const std::string& sql)
{
// apply examples
}
};
并在这里打电话:
database db;
User result = db.select_<User, int, std::string, std::string>
("select id, email, name from credentials_tbl limit 1");
我错过了什么?
这里有一个完整的例子,我希望它包含所有内容:
(当 运行 Microsoft Visual Studio 2013 我得到同样的错误)
// 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 */
// ------------- 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;
}
无论问题的上下文如何,我通常希望 selector_helper
类型看起来更像:
template <typename...> struct iSelectable;
template<typename TT>
struct selector_helper
{
template<class... Ts>
static TT doSelect(Ts&&... params) {
return iSelectable<Ts...>::template select<TT>(std::forward<Ts>(params)...);
}
};
请注意嵌套 select
模板上的额外 template
限定条件。如果 select
是一种类型(我们怎么知道),您可能也需要 typename
:Where and why do I have to put the "template" and "typename" keywords?
更新
查看更完整的示例,正是这个问题。 do_select
的模板参数已明确指定:
return apply(selector_helper<T, Ts...>::doSelect, tpl);
这行不通,因为它抑制了模板参数推导,并且签名被强制为
User (&)(int&&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)
当然,虽然元组实际上是
boost::tuples::tuple<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, ...>&
您可以看到 Args...
.
的推导类型存在冲突
实际上我会通过不那么具体来简化这个:
template <class Ret, class Tuple, class... Args, int... Indexes>
Ret apply_helper(Ret (*pf)(Args...), index_tuple<Indexes...>, Tuple&& tup) {
return pf(std::forward<Args>(get<Indexes>(std::forward<Tuple>(tup)))...);
}
template <class Ret, class Tuple, class... Args>
Ret apply(Ret (*pf)(Args...), Tuple&& tup) {
return apply_helper(pf, typename make_indexes<Args...>::type(), std::forward<Tuple>(tup));
}
这已经编译
// 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>
#include <boost/make_shared.hpp>
#define _TCHAR char
using namespace boost;
/* apply methods from
*
*/
// ------------- 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 Tuple, class... Args, int... Indexes>
Ret apply_helper(Ret (*pf)(Args...), index_tuple<Indexes...>, Tuple&& tup) {
return pf(std::forward<Args>(get<Indexes>(std::forward<Tuple>(tup)))...);
}
template <class Ret, class Tuple, class... Args>
Ret apply(Ret (*pf)(Args...), Tuple&& tup) {
return apply_helper(pf, typename make_indexes<Args...>::type(), std::forward<Tuple>(tup));
}
/* end of apply methods */
/* class iSelectable */
template <typename...> struct iSelectable;
template <class... Ts> struct iSelectable {
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...>::template 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 { -123, "fame", "something" };
/* This is where my errors occur: */
return apply(selector_helper<T, Ts...>::doSelect, tpl);
return {123, "name", "something"};
}
};
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_ = boost::make_shared<postgres_database_impl>();
};
class User : public iSelectable<int, std::string, std::string> {
public:
User(int id, std::string name, std::string surname)
: id(id), name(std::move(name)), surname(std::move(surname)) {
}
private:
int id;
std::string name;
std::string surname;
friend std::ostream& operator << (std::ostream& os, User const& user) {
return os << user.id << ", " << user.name << ", " << user.surname << "\n";
}
};
int main() {
Database db;
User result =
db.select_<User, int, std::string, std::string>("select id, email, name from credentials_tbl limit 1");
std::cout << "Result: " << result << "\n";
}
输出:
Result: -123, fame, something
我认为我看到了很多进一步简化的机会,但老实说,我需要更多地了解开始这一旅程的目标。
我在使用 apply 函数时遇到以下代码中的歧义问题。它基于 Whosebug 问题 here.
1) 我有一个助手 class,因为模板函数作为指针是不允许的:
template<typename TT, class...Ts>
struct selector_helper
{
static TT doSelect(Ts&&... params)
{
return iSelectable<Ts...>::select<TT>(std::forward<Ts>(params)...);
}
};
我尝试运行应用函数,但是运行遇到了问题。我尝试了两个代码,但没有一个成功:
2.1) 错误:应用:2 个重载中的 none 可以转换所有参数类型
boost::tuple<Ts...> tpl;
return apply<T, Ts...>(selector_helper<T, Ts...>::doSelect, tpl);
2.2) 这里我得到两个错误:
- 错误 2 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),boost::tuples::tuple &&)' : 模板参数 'Args' 不明确
错误 3 error C2782: 'Ret apply(Ret (__cdecl *)(Args...),const boost::tuples::tuple &)' : 模板参数 'Args' 不明确
boost::tuple<Ts...> tpl; return apply(selector_helper<T, Ts...>::doSelect, tpl);
编辑:更多解释:
两个例子都运行内嵌在select方法中,它在class:
中class database
{
template<typename T, typename...Ts>
T select_(const std::string& sql)
{
// apply examples
}
};
并在这里打电话:
database db;
User result = db.select_<User, int, std::string, std::string>
("select id, email, name from credentials_tbl limit 1");
我错过了什么?
这里有一个完整的例子,我希望它包含所有内容: (当 运行 Microsoft Visual Studio 2013 我得到同样的错误)
// 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 */
// ------------- 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;
}
无论问题的上下文如何,我通常希望 selector_helper
类型看起来更像:
template <typename...> struct iSelectable;
template<typename TT>
struct selector_helper
{
template<class... Ts>
static TT doSelect(Ts&&... params) {
return iSelectable<Ts...>::template select<TT>(std::forward<Ts>(params)...);
}
};
请注意嵌套 select
模板上的额外 template
限定条件。如果 select
是一种类型(我们怎么知道),您可能也需要 typename
:Where and why do I have to put the "template" and "typename" keywords?
更新
查看更完整的示例,正是这个问题。 do_select
的模板参数已明确指定:
return apply(selector_helper<T, Ts...>::doSelect, tpl);
这行不通,因为它抑制了模板参数推导,并且签名被强制为
User (&)(int&&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)
当然,虽然元组实际上是
boost::tuples::tuple<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, ...>&
您可以看到 Args...
.
实际上我会通过不那么具体来简化这个:
template <class Ret, class Tuple, class... Args, int... Indexes>
Ret apply_helper(Ret (*pf)(Args...), index_tuple<Indexes...>, Tuple&& tup) {
return pf(std::forward<Args>(get<Indexes>(std::forward<Tuple>(tup)))...);
}
template <class Ret, class Tuple, class... Args>
Ret apply(Ret (*pf)(Args...), Tuple&& tup) {
return apply_helper(pf, typename make_indexes<Args...>::type(), std::forward<Tuple>(tup));
}
这已经编译
// 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>
#include <boost/make_shared.hpp>
#define _TCHAR char
using namespace boost;
/* apply methods from
*
*/
// ------------- 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 Tuple, class... Args, int... Indexes>
Ret apply_helper(Ret (*pf)(Args...), index_tuple<Indexes...>, Tuple&& tup) {
return pf(std::forward<Args>(get<Indexes>(std::forward<Tuple>(tup)))...);
}
template <class Ret, class Tuple, class... Args>
Ret apply(Ret (*pf)(Args...), Tuple&& tup) {
return apply_helper(pf, typename make_indexes<Args...>::type(), std::forward<Tuple>(tup));
}
/* end of apply methods */
/* class iSelectable */
template <typename...> struct iSelectable;
template <class... Ts> struct iSelectable {
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...>::template 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 { -123, "fame", "something" };
/* This is where my errors occur: */
return apply(selector_helper<T, Ts...>::doSelect, tpl);
return {123, "name", "something"};
}
};
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_ = boost::make_shared<postgres_database_impl>();
};
class User : public iSelectable<int, std::string, std::string> {
public:
User(int id, std::string name, std::string surname)
: id(id), name(std::move(name)), surname(std::move(surname)) {
}
private:
int id;
std::string name;
std::string surname;
friend std::ostream& operator << (std::ostream& os, User const& user) {
return os << user.id << ", " << user.name << ", " << user.surname << "\n";
}
};
int main() {
Database db;
User result =
db.select_<User, int, std::string, std::string>("select id, email, name from credentials_tbl limit 1");
std::cout << "Result: " << result << "\n";
}
输出:
Result: -123, fame, something
我认为我看到了很多进一步简化的机会,但老实说,我需要更多地了解开始这一旅程的目标。