function<T>
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了function<T>相关的知识,希望对你有一定的参考价值。
参考技术A boost::function<bool(void, int)> funcc++11 后:
std::function包含于头文件 #include<functional>中
function<T>是一个模板类,封装有函数指针类型,即T一定要是函数指针类型。
1. 把不同的函数类型统一成同一种类型,从而为模板函数提供统一接口。
2. 简化了函数指针的声明
可将各种可调用实体进行封装统一,包括:普通函数、lambda、表达式、函数指针、仿函数
function模板相对于一般模板的优点就是模板实例化次数更少,一般模板对上述每种类型都要实例化依次,function模板对类型相同的各种类型只实例化一次
//普通函数
int add(int a, int b)
return a+b;
//lambda表达式
auto mod=[](int a, int b)return a%b;;
//函数对象
struct divide
int operator()(int m, int n)
return m/n;
;
function<int(int,int)> func1= add;
function<int(int,int)> func2= divide();
function<int(int,int)> func3= mod;
//被封装后普通函数、Lambda、函数对象对属于同一个类型,放到函数模板中后,只实例化一次
function<T> 就是对函数、lambda函数指针的封装,T为函数指针类型。
定义多种类型转换构造函数,就可以把lambda函数指针、普通函数指针、函数对象等转换为function类型。
从 IEnumerable<T> 函数返回字符串
【中文标题】从 IEnumerable<T> 函数返回字符串【英文标题】:Returning a string from an IEnumerable<T>function 【发布时间】:2021-12-30 09:27:23 【问题描述】:我可能做错了什么,但我正在尝试做this Kata on Codewars
下面是我当前的代码。
public static class Kata
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> arr)
Type t = typeof(T);
if (t == typeof(string))
return (IEnumerable<T>)String.Join("",arr.Distinct()).AsEnumerable();
return arr.Distinct().ToArray();
此 kata 的单元测试期望输入“AAAABBBCCDAABBB”返回为“ABCDAB”。
我上面的代码由于这个错误而失败
Expected is <System.String>, actual is <System.Char[6]>
如果我尝试返回一个字符串,我会收到以下错误:error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'
如果我无法返回字符串(并且 char 数组失败),我如何返回预期的字符串?
谢谢
【问题讨论】:
你传递了一个string
,这是一个IEnumerable<char>
,而不是IEnumerable<string>
,这意味着T
是char
而不是string
,所以你的if (t == typeof(string))
返回false
。
请注意,您不能简单地通过调用.Distinct()
来解决此问题;如果是这样,就没有挑战了。
你的返回类型是IEnumerable<T>
,但你断言它是string
。
另外......没有理由打电话给ToArray()
。它只是浪费内存和cpu。 Distinct()
方法本身已经完成了您的 IEnumerable 合同。如果调用者实际上想要一个数组(或列表,或其他),让他们做出选择。
用老式的方法来做。循环遍历 IEnumerable,如果元素 i
与元素 i-1
相同,则将其丢弃。如果没有,yield return
它
【参考方案1】:
应该这样做:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext(); //start iterating
while (EnumeratorActive)
// set and yield the current value
T cur = e.Current;
yield return cur;
// keep advancing while the iterator is active and additional values match the current val
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()))
//empty body intentional
它使用称为 Control/Break 的嵌套 while 循环模式,该模式仍以线性时间运行(因为只有内部循环在前进)。
这是一个没有额外解释的简化版本:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext();
while (EnumeratorActive)
T cur = e.Current;
yield return cur;
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()));
【讨论】:
如果序列包含null
的元素(这可能是允许的;至少没有理由假设它不是),则此操作失败。如果你不打算使用EqualityComparer
,你也可以使用静态Object.Equals
。【参考方案2】:
你可以这样实现它(因为你已经使用了<T>
,让我们用自定义comparer
实现一般情况解决方案):
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> source,
IEqualityComparer<T> comparer = null)
if (null == source)
throw new ArgumentNullException(nameof(source));
comparer ??= EqualityComparer<T>.Default;
bool first = true;
T prior = default; // default: let compiler be happy
foreach (T item in source)
if (first || !comparer.Equals(item, prior))
prior = item;
first = false;
yield return item;
这里我们只检查当前item
是否等于prior
。
演示:
string source = "AAAABBBCCDAABBB";
string result = string.Concat(UniqueInOrder(source));
Console.Write(result);
结果:
ABCDAB
编辑:请注意
中的Distinct()
arr.Distinct()
删除整个 arr
中的重复项,这就是为什么你只会得到 4 个不同的字符:
AAAABBBCCDAABBB -> ABCD
Distinct()
在给定的问题中,我们有一个较弱条件:当前项不能等于先前项。
【讨论】:
不错!我只是在测试他们的测试:Expected is <System.String>, actual is <System.Linq.Enumerable+DistinctIterator
1[System.Char]>` 所以让我们教初学者Distinct
的奇妙用法,然后跳出惊人的循环来获得满足测试的正确返回类型。他们为什么要将字符串交给这样的方法。这在现实世界中不会发生……除非您使用的是 Java。 (我使用 java,没有深入了解火焰战争。:P)以上是关于function<T>的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3903 Trigonometric Function