我有许多不相关的类型,它们都通过重载的自由函数(ad hoc多态)支持相同的操作:
struct A {};
void use(int x) { std::cout << "int = " << x << std::endl; }
void use(const std::string& x) { std::cout << "string = " << x << std::endl; }
void use(const A&) { std::cout << "class A" << std::endl; }
Run Code Online (Sandbox Code Playgroud)
正如问题的标题所暗示的那样,我希望将这些类型的实例存储在异构容器中,这样use()
无论它们具体是什么类型,我都可以使用它们.容器必须具有值语义(即两个容器之间的赋值复制数据,它不共享它).
std::vector<???> items;
items.emplace_back(3);
items.emplace_back(std::string{ "hello" });
items.emplace_back(A{});
for (const auto& item: items)
use(item);
// or better yet
use(items);
Run Code Online (Sandbox Code Playgroud)
当然,这必须是完全可扩展的.考虑一个带有a的库API vector<???>
,以及将自己的类型添加到已知类型的客户端代码.
通常的解决方案是将(智能)指针存储到(抽象)接口(例如vector<unique_ptr<IUsable>>
),但这有许多缺点 - 从我的头脑:
我看到了这个漂亮的图形,它根据不同的数据要求对哪个STL容器进行分类,例如:
- 固定尺寸Vs可变尺寸
- 相同tyme的数据Vs不同类型
- 排序Vs未排序的数据
- 顺序Vs随机访问
http://plasmahh.projectiwear.org/cce_clean.svg
我在那张图片中注意到,C++ STL没有容器
C++有没有这方面的东西?
PS - 容器的不同属性可以有许多排列,STL也可能没有提供许多其他属性.
我正在尝试编码一个项目列表,这些项目的类型仅限于某些类型类的实例:
{-# LANGUAGE RankNTypes, TypeSynonymInstances, LiberalTypeSynonyms #-}
module Test where
class Someable a where
some :: a -> String
data Some = Some String
type SomeGroup = forall a. Someable a => [a]
instance Someable Some where
some (Some v) = v
instance Someable SomeGroup where
some (x:xs) = (some x) ++ ", " ++ (some xs)
main = do
putStrLn $ show.some [Some "A", [Some "B", Some "C"]]
Run Code Online (Sandbox Code Playgroud)
但编译失败并出现错误:
Test.hs:14:10:
Illegal polymorphic or qualified type: SomeGroup
In the instance …
Run Code Online (Sandbox Code Playgroud) 我正在尝试通过一些任意类型的数组实现一个在内存中遵循的类:
template<class T>
class Buf
{
size_t n;
int refs;
explicit Buf(size_t n) : n(n) { }
// other declarations are here as appropriate
// Followed in memory by:
// T items[n];
};
Run Code Online (Sandbox Code Playgroud)
这很简单operator new
:
template<class T>
Buf<T> *make_buf(size_t n)
{
// Assume the caller will take care of constructing the array elements
return new(operator new(sizeof(Buf<T>) + sizeof(T) * n)) Buf<T>(n);
}
template<class T>
void free_buf(Buf<T> *p)
{
// Assume the caller has taken care of destroying the …
Run Code Online (Sandbox Code Playgroud) 我在哪里可以找到Data.HList的简单使用示例?从我在维基中读到的内容来看,这个工具对于异构列表来说是一个"更好"的解决方案,而不是存在类型,我不明白为什么.
在我看来,在.classpath等文件中添加属性svn:ignore是个好主意.我同时使用Windows(work,ugh)和Linux开发环境,每次与存储库同步时,它都会覆盖我正在处理的任何一台机器上的.classpath.
我尝试在Team Sync透视图中右键单击.classpath文件,但svn:ignore选项显示为灰色.
任何想法我可能:1.从源代码控制中获取此项,2.将其添加到忽略列表?
任何其他文件智能添加到此列表?
HList
按类型过滤很容易:
val hlist = 1 :: 2 :: "3" :: true :: false :: HNil
hlist.filter[Int]
Run Code Online (Sandbox Code Playgroud)
但是如何制作我的自定义类型过滤器?我想要那样的smth:例如我得到了一些函数的列表:
def function1(s: String) = s.toInt
def function2(s: String) = s.toDouble
def function3(i: Int) = i.toDouble
val hflist = function1 _ :: function3 _ :: function2 _ :: HNil
hflist customFilter[String] //> function1 _ :: function2 _ :: HNil
Run Code Online (Sandbox Code Playgroud)
因此,在使用此过滤器之后,String
将构造从类型到其他类型的函数列表.
我有一个想法,为此使用地图,但它没有成功.
版
有关我的评论的更多信息:
我试图在地图上测试这个想法:
所以,如果我有一些列表(让我们使用hlist
&hflist
):
object allFunction extends Poly1 {
implicit def default[T, M] =
at[T => …
Run Code Online (Sandbox Code Playgroud) 使用Scala标准库时,我可以做这样的事情:
scala> val scalaList = List(1,2,3)
scalaList: List[Int] = List(1, 2, 3)
scala> scalaList.foldLeft(0)((acc,n)=>acc+n)
res0: Int = 6
Run Code Online (Sandbox Code Playgroud)
从许多Int中取出一个Int.
我可以这样做:
scala> scalaList.foldLeft("")((acc,n)=>acc+n.toString)
res1: String = 123
Run Code Online (Sandbox Code Playgroud)
从许多Int中制作一个String.
因此,foldLeft可以是同构的,也可以是异构的,无论我们想要什么,它都在一个API中.
在Spark中,如果我想要很多Int中的一个Int,我可以这样做:
scala> val rdd = sc.parallelize(List(1,2,3))
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:12
scala> rdd.fold(0)((acc,n)=>acc+n)
res1: Int = 6
Run Code Online (Sandbox Code Playgroud)
fold API类似于foldLeft,但它只是同类的,RDD [Int]只能生成带折叠的Int.
Spark中也有一个聚合API:
scala> rdd.aggregate("")((acc,n)=>acc+n.toString, (s1,s2)=>s1+s2)
res11: String = 132
Run Code Online (Sandbox Code Playgroud)
它是异构的,RDD [Int]现在可以生成一个String.
那么,为什么fold和聚合在Spark中实现为两个不同的API?
为什么它们的设计不像foldLeft那样可以是同构的还是异构的?
(我对Spark很新,请原谅我这是一个愚蠢的问题.)
scala aggregate heterogeneous homogenous-transformation apache-spark
我遇到了一种我确定并不常见的情况.我有两个符合协议的对象数组,我想检查它们是否相等.
我真正想做的是:
protocol Pattern: Equatable
{
func isEqualTo(other: Pattern) -> Bool
}
func ==(rhs:Pattern, lhs:Pattern) -> Bool
{
return rhs.isEqualTo(lhs)
}
extension Equatable where Self : Pattern
{
func isEqualTo(other: Pattern) -> Bool
{
guard let o = other as? Self else { return false }
return self == o
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这会导致编译错误:
Error:(10, 30) protocol 'Pattern' can only be used as a generic constraint because it has Self or associated type requirements
基于这篇文章,我意识到我需要在协议上丢失Equatable继承并将其推送到具体的"Pattern"声明.虽然我真的不明白为什么.如果我通过重载来定义基于协议的两个对象是如何相等的==就我所见,确实没有问题.我甚至不需要知道实际类型或它们是类还是结构.
无论如何,这一切都很好,我现在可以比较,concretePattern.isEqualTo(otherConcretePattern)
但问题仍然是我不能再比较这些对象的数组,就像我可以比较具体类型的数组,因为数组相等依赖于重载==运算符.
到目前为止,我设法做到的最好的 …
我如何通过一些HList
作为参数?所以我可以这样做:
def HFunc[F, S, T](hlist: F :: S :: T :: HNil) {
// here is some code
}
HFunc(HList(1, true, "String")) // it works perfect
Run Code Online (Sandbox Code Playgroud)
但是,如果我有一个很长的清单,我不知道它,我怎么能对它做一些操作?我如何通过论证而不是松散其类型?
heterogeneous ×10
c++ ×3
scala ×3
containers ×2
haskell ×2
list ×2
polymorphism ×2
shapeless ×2
aggregate ×1
allocator ×1
apache-spark ×1
arrays ×1
c++11 ×1
classpath ×1
filter ×1
generics ×1
hlist ×1
protocols ×1
stl ×1
subclipse ×1
svn ×1
svnignore ×1
swift ×1
swift2 ×1
typeclass ×1
types ×1