- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想做一个std::function
像可以处理存储多个重载的对象。
语法有点像这样:my_function< int(double, int), double(double, double), char(int, int) >
.
或者,更明确地说:
template<typename... Ts>
struct type_list {};
template<typename... Signatures >
struct my_function {
std::tuple< std::function<Signatures>... > m_functions;
typedef type_list< Signatures... > sig_list;
template<typename... Args>
typename pick_overload_signature< sig_list, type_list<Args...> >::return_value
operator()( Args&&... args )
{
return get<pick_overload_signature< sig_list, type_list<Args...> >::index>(m_functions)(std::forward<Args>(args)...);
}
};
我的问题:我应该怎么写pick_overload_signatures
?
这是我在上面所做的工作:
我的倾向是针对给定的一组参数编写函数签名的部分顺序,然后对函数签名的类型列表进行排序,然后获取最好的(可能在编译时断言最好的是独特的)。要做到这一点,我必须对函数签名有一个可靠的偏序(关于传入的一组参数)...
13.3.3.1 告诉我如何确定是否存在有效转换。我可以通过使用编译器为我进行转换来作弊,并使用 SFINAE 检测它是否发生在传入的给定参数和其中一个“重载”的签名上。
13.3.3.2 告诉我如何对这些转换进行排序。在这里,我必须检测转换序列是用户定义的还是标准序列。我不确定如何区分这两者。
也许我可以使用 traits 类来检测用户定义的转换序列的存在。检查 &S::operator D()
是否存在和 &D::D(S const&)
和 &D::D(S)
和 &D::D(S&&)
或类似的东西。
has_user_defined_conversion<S,D>::value
, has_standard_conversion<S,D>::value
等等?
这种方法行得通吗?有人已经这样做了吗?或者有人已经完成了其中的一部分?
#include <type_traits>
#include <cstddef>
#include <utility>
#include <functional>
#include <tuple>
#include <string>
// Packaged list of types:
template<typename... Ts>
struct type_list {
template<template<typename...>class target>
struct apply {
typedef target<Ts...> type;
};
template<typename T>
struct append {
typedef type_list< Ts..., T > type;
};
template<typename T>
struct prepend {
typedef type_list< T, Ts... > type;
};
};
template<template<typename>class mapper, typename list>
struct map_types {
typedef type_list<> type;
};
template<template<typename>class mapper, typename T0, typename... Ts>
struct map_types<mapper, type_list<T0, Ts...>> {
typedef typename map_types<mapper, type_list<Ts...>>::type tail;
typedef typename tail::template prepend< typename mapper<T0>::type >::type type;
};
template<template<typename>class mapper, typename list>
using MapTypes = typename map_types<mapper, list>::type;
template<template<typename>class temp>
struct apply_template_to {
template<typename T>
struct action {
typedef temp<T> type;
};
};
template<template<typename> class temp, typename list>
struct apply_to_each:map_types< apply_template_to<temp>::template action, list > {};
template<template<typename> class temp, typename list>
using ApplyToEach = typename apply_to_each<temp, list>::type;
template<std::size_t n, typename list>
struct nth_type {};
template<std::size_t n, typename first, typename... elements>
struct nth_type<n, type_list<first, elements...>>:nth_type<n-1, type_list<elements...>>
{};
template<typename first, typename... elements>
struct nth_type<0, type_list<first, elements...>>
{
typedef first type;
};
template<std::size_t n, typename list>
using NthType = typename nth_type<n, list>::type;
// func data
template<typename R, typename... Args>
struct unpacked_func {
typedef R result_type;
typedef type_list<Args...> args_type;
typedef unpacked_func< R, Args... > unpacked_type;
template<template<typename>class target>
struct apply {
typedef target<R(Args...)> type;
};
};
namespace unpack_details {
// Extracting basic function properties:
template<typename Func>
struct unpack_func {};
template<typename R, typename... Args>
struct unpack_func< R(Args...) > {
typedef unpacked_func< R, Args... > type;
};
template<typename R, typename... Args>
struct unpack_func< unpacked_func<R, Args...> >:
unpack_func< R(Args...) >
{};
}
template<typename Func>
using FuncUnpack = typename unpack_details::unpack_func<Func>::type;
template<typename Func>
struct func_props:func_props<FuncUnpack<Func>> {};
template<typename R, typename... Args>
struct func_props<unpacked_func<R, Args...>>:
unpacked_func<R, Args...>
{};
template<typename Func>
using FuncResult = typename func_props<Func>::result_type;
template<typename Func>
using FuncArgs = typename func_props<Func>::args_type;
template<typename Func>
struct make_func_ptr:make_func_ptr<FuncUnpack<Func>> {};
template<typename R, typename... Args>
struct make_func_ptr< unpacked_func< R, Args... > > {
typedef R(*type)(Args...);
};
template<typename Func>
using MakeFuncPtr = typename make_func_ptr<Func>::type;
// Marking a type up with an index:
template<typename R, std::size_t i>
struct indexed_type {
typedef R type;
enum { value = i };
};
// Sequences of size_t:
template<std::size_t... s>
struct seq {};
template<std::size_t min, std::size_t max, std::size_t... s>
struct make_seq: make_seq< min, max-1, max-1, s...> {};
template<std::size_t min, std::size_t... s>
struct make_seq< min, min, s...> {
typedef seq<s...> type;
};
template<std::size_t max, std::size_t min=0>
using MakeSeq = typename make_seq<max, min>::type;
namespace overload_details {
template<std::size_t n, typename... Overloads>
struct indexed_linear_signatures {};
template<typename Overload>
struct signature_generator {};
template<typename R, typename... Args>
struct signature_generator<unpacked_func<R, Args...>> {
R operator()(Args...); // no impl
};
template<typename Func, std::size_t i>
struct indexed_retval {};
template<typename R, typename... Args, std::size_t i>
struct indexed_retval< unpacked_func<R, Args...>, i > {
typedef unpacked_func<indexed_type<R,i>, Args...> type;
};
template<typename Func, std::size_t i>
using IndexRetval = typename indexed_retval<Func,i>::type;
void test1() {
typedef overload_details::IndexRetval< FuncUnpack<void()>, 0 > indexed;
indexed::apply<std::function>::type test = []()->indexed_type<void,0> {return indexed_type<void,0>();};
}
template<std::size_t n, typename Overload, typename... Overloads>
struct indexed_linear_signatures<n, Overload, Overloads...>:
signature_generator<IndexRetval<FuncUnpack<Overload>,n>>,
indexed_linear_signatures<n+1, Overloads...>
{};
template<typename T>
struct extract_index {};
template<typename T, std::size_t i>
struct extract_index<indexed_type<T,i>> {
enum {value = i};
};
template<typename T>
using Decay = typename std::decay<T>::type;
template<typename indexed_overloads, typename... Args>
struct get_overload_index {
enum{ value = extract_index< Decay<decltype( std::declval<indexed_overloads>()(std::declval<Args>()...) )> >::value };
};
template<typename Overloads, typename Args>
struct get_overload {};
template<typename... Overloads, typename... Args>
struct get_overload<type_list<Overloads...>, type_list<Args...>> {
typedef indexed_linear_signatures<0, Overloads...> sig_index;
enum { index = get_overload_index< sig_index, Args... >::value };
typedef FuncUnpack< NthType<index, type_list<Overloads...> > > unpacked_sig;
};
template<typename Overloads, typename Args>
using GetOverloadSig = typename get_overload< Overloads, Args >::unpacked_sig;
}
template<typename Overloads, typename Arguments>
struct pick_overload_signature {
enum{ index = overload_details::get_overload<Overloads, Arguments>::index };
typedef overload_details::GetOverloadSig<Overloads, Arguments> unpacked_sig;
};
#include <iostream>
void test1() {
typedef type_list< void(int), void(double) > overloads;
typedef type_list< int > args;
typedef pick_overload_signature< overloads, args > result;
std::cout << result::index << " should be 0\n";
typedef type_list< double > args2;
typedef pick_overload_signature< overloads, args2 > result2;
std::cout << result2::index << " should be 1\n";
// ;
typedef ApplyToEach< std::function, overloads >::apply< std::tuple >::type functions;
typedef std::tuple< std::function<void(int)>, std::function<void(double)> > functions0;
std::cout << std::is_same<functions, functions0>() << " should be true\n";
functions funcs{
[](int) { std::cout << "int!" << "\n"; },
[](double) { std::cout << "double!" << "\n"; }
};
std::get<result::index>(funcs)(0);
}
template< typename... Signatures >
struct my_function {
typedef type_list<Signatures...> signatures;
typedef std::tuple< std::function<Signatures>... > func_tuple;
func_tuple functions;
template<typename... Funcs>
explicit my_function(Funcs&&... funcs):
functions( std::forward<Funcs>(funcs)... )
{}
template<typename... Args>
auto
operator()(Args&&... args) const ->
typename overload_details::GetOverloadSig< signatures, type_list<Args...> >::result_type
{
return std::get<
pick_overload_signature< signatures, type_list<Args...> >::index
>(functions)(std::forward<Args>(args)...);
}
// copy/assign boilerplate
template<typename... OtherSignatures>
my_function( my_function<OtherSignatures...> const& o ):
functions( o.functions )
{}
template<typename... OtherSignatures>
my_function( my_function<OtherSignatures...> && o ):
functions( std::move(o.functions) )
{}
template<typename... OtherSignatures>
my_function& operator=( my_function<OtherSignatures...> const& o )
{
functions = o.functions;
return *this;
}
template<typename... OtherSignatures>
my_function& operator=( my_function<OtherSignatures...> && o ) {
functions = std::move(o.functions);
return *this;
}
};
struct printer {
template<typename T>
void operator()( T const& t ) {
std::cout << t << "\n";
}
};
void print(int x) {
std::cout << "int is " << x << "\n";
}
void print(std::string s) {
std::cout << "string is " << s << "\n";
}
void test2() {
my_function< void(int), void(std::string) > funcs{
[](int x){ std::cout << "int is " << x << "\n";},
[](std::string s){ std::cout << "string is " << s << "\n";}
};
std::cout << "test2\n";
funcs("hello");
funcs(0);
my_function< void(int), void(std::string) > funcs2{
printer(), printer()
};
funcs2("hello");
funcs2(12.7);
// doesn't work:
/*
my_function< void(int), void(std::string) > funcs3{
print,
print
};
*/
}
void test3() {
}
int main() {
test1();
test2();
test3();
}
尚未完成,但可用。
谢谢大家!
最佳答案
我确定它是可行的,但您可能会对这个感到满意 https://gist.github.com/dabrahams/3779345
template<class...Fs> struct overloaded;
template<class F1, class...Fs>
struct overloaded<F1, Fs...> : F1, overloaded<Fs...>::type
{
typedef overloaded type;
overloaded(F1 head, Fs...tail)
: F1(head),
overloaded<Fs...>::type(tail...)
{}
using F1::operator();
using overloaded<Fs...>::type::operator();
};
template<class F>
struct overloaded<F> : F
{
typedef F type;
using F::operator();
};
template<class...Fs>
typename overloaded<Fs...>::type overload(Fs...x)
{ return overloaded<Fs...>(x...); }
auto f = overload(
[](int x) { return x+1; },
[](char const* y) { return y + 1; },
[](int* y) { return y; });
关于c++ - "Manual"签名重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14972954/
假设我有一个类,我在其中重载了运算符 == : Class A { ... public: bool operator== (const A &rhs) const; ... };
我知道你不应该使用 std::find(some_map.begin(), some_map.end()) 或 std::lower_bound,因为它会采用线性时间而不是 some_map.lowe
我正在尝试在 Haskell 中定义 Vector3 数据类型,并允许在其上使用 (+) 运算符。我尝试了以下方法: data Vector3 = Vector3 Double Double Doub
我已经为我的类图将运算符重载为“-”。它的用途并不完全直观(糟糕的编码 - 我知道)但是如果我做 graph3 = graph2-graph1 那么图 3 是应该只接收图 2 和图 1 中的那些顶点。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Operator overloading 我想重载 以按字母顺序排列字符串,但我不确定该怎么做。 如何再次
下面的代码给我一个编译错误。谁能告诉我为什么? class mytype { public: int value; mytype(int a) { value = a;
这有什么问题吗? class Vec2 attr_accessor :x, :y # ... def += (v) @x += v.x @y += v.y retu
是否可以重载 [] 运算符两次?允许这样的事情:function[3][3](就像在二维数组中一样)。 如果可能的话,我想看看一些示例代码。 最佳答案 您可以重载 operator[] 以返回一个对象
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
我有一个网页,在某个时候显示一个导航栏,它只不过是一个 a 元素的列表 (ul)。所述 a 元素的大多数样式规则都是通用的。唯一应该改变的部分是要显示的图像,可以从列表中每个 li 元素的 id 标签
我对使用/重载“范围步长”运算符(.. ..)很感兴趣,但我终其一生都无法了解如何使用它。 在文档中它说 // Usage: start .. step .. finish 但是在 F# shell
Java 11(可能无关紧要): public static String toString(Object obj) { return ReflectionToStringBuilder.to
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我无法理解以下代码(针对行号进行注释) class Base { void m1(Object o) { } void m2(String o) { } } publi
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
class myclass{ //definitions here }; myclass e; int myarray[10]; /* Do something... */ e = myarray;
为什么不能将下标运算符(operator [])作为 friend 函数重载? 最佳答案 正如Bjarne Stroustrup在D&E book中所说: However, even in the o
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
因此,我有一个问题是我最近尝试重载 namespace Eng { /** * A structure to represent pixels */ typedef
如何重载onResume()以正确的方式工作?我想从 activity 返回到 MainActivity ,我希望在其中具有与应用程序启动后相同的状态。我想使用 recreate() 但它循环了或者类
我是一名优秀的程序员,十分优秀!