Is there a decltype equivalent in Swift? - c++

In C++11 and latter, it is possible to use a compile time function like syntax named decltype() to reuse declaration type of a variable to declare another one without rewriting the type signature. Is there any equivalent syntactic tool in Swift?
C++ Example:
class SomeClass {
public:
SomeVeryLongTypeName* my_prop;
}
void foo() {
SomeClass my_var = SomeClass();
// Below code is a variable declaration, not a function call
declytype(my_var.my_prop) some_prop = nullptr;
// Below is same as above
SomeVeryLongTypeName* some_prop = nullptr;
}

There is, as far as I know, no direct equivalent syntactic tool readily available in Swift.
For something slightly similar you could, however, make use of generics to gain access to (at compile time) a metatype (grammar: metatype-type → type­.­Type), whereafter you can use an initializer expression to construct an instance of the concrete type (of the metatype).
protocol Initializable {
init()
}
typealias SomeVeryLongTypeName = Int
extension SomeVeryLongTypeName : Initializable {}
class SomeClass {
let my_prop : SomeVeryLongTypeName
required init() { my_prop = 1 }
}
func declmetatype<T: Initializable>(_: T) -> T.Type {
return T.self
}
func foo() {
let my_var = SomeClass()
let some_prop = declmetatype(my_var.my_prop).init()
some_prop = my_var.my_prop + 1
}
In foo() above, some_prop is of type SomeVeryLongTypeName (which, here, is simply Int), which due to Swift's static typing is naturally known at compile time.
Note, however, that in Swift we cannot use this technique to only declare types, but must also instantiate them. Moreover, there's no concept of "default initializers" in Swift (as compared to default CTOR:s in C++), hence the need to constrain the generic typeholder in declmetatype(...) to a protocol of our own, where we provide a blueprint to some initializer we'd like to use in a "default sense" from the metatype.
We may visit the Language Reference - Types - Metatypes for additional details on metatypes, particularly:
Use an initializer expression to construct an instance of a type
from that type’s metatype value. For class instances, the initializer
that’s called must be marked with the required keyword or the entire
class marked with the final keyword.
Where I've emphasized the available use of metatypes to construct instances of types (as shown above), which does not, however, cover using metatypes to only declare types.

Related

Is it possible to parameterize a generic with a type that is itself generic? [duplicate]

Is it possible to do something like this in Rust?
trait Foo<T> {}
struct A;
struct B;
struct Bar<T: Foo> {
a: T<A>,
b: T<B>
}
I know I could just use two parameters for Bar, but I think there has to be a better way to do this.
I want to implement a Graph structure. As I can't just bind the nodes and edges to their parents lifetime, I want to have something like Rc. However, sometimes one may need a Graph with access from multiple threads. So I'd have to have both an implementation with Rc and Arc.
That's what Foo is good for: I implement Foo for both Rc and Arc (Foo would require Deref) and I use a parameter T bound to Foo. That's how I wanted to have one struct for single thread and multi thread usage.
⇒ This is currently impossible to express in Rust's type system ☹
Fortunately, it will be possible in the future thanks to "Generic Associated Types" as proposed in this RFC. You can track the status of implementation and stabilization in the corresponding tracking issue.
The important term here is "HKT" (higher kinded types). It's a feature of a type system which is not yet implemented in Rust. Haskell offers HKTs. In the C++ world HKTs are known as "template templates". The generic associated types mentioned above are also a form of HKTs.
But what are HKTs, really?
Let's start slowly: what is a simple type as we know it? Let's list some types: i32, bool, String. These are all types... you can have a value (variable) of these types. What about Vec<i32>? It's also a simple type! You can have a variable of type Vec<i32>, no problem!
We want to group these types together; we call this categorisation a "kind of a type". If we want to talk in a very abstract way (about types of types) we choose other words, kind in this case. There is even a notation for kinds of types. For our simple types from above, we say: the kind of those types is
*
Yes, just a star, very easy. The notation makes more sense later!
Let's search for types that are of a different kind than our simple types. Mutex<HashMap<Vec<i32>, String>>? Nope, it's fairly complex maybe, but it's still of kind * and we still can have a variable of that type.
What about Vec? Yes, we omitted the angle-brackets. Yes, this is indeed another kind of type! Can we have a variable of type Vec? No! A vector of what?!
This kind is donated as:
* -> *
This just says: give me a normal type (*) and I will return a normal type! Give a normal type i32 to this thing (Vec) and it will return a normal type Vec<i32>! It's also called a type constructor, because it is used to construct types. We can even go further:
* -> * -> *
This is a bit strange, because it has to do with currying and reads odd for a non-Haskell programmer. But it means: give me two types and I will return a type. Let's think about an example... Result! The Result type constructor will return a concrete type Result<A, B> after you provided two concrete types A and B.
The term higher kinded types just refers to all kinds of types which are not *, which are type constructors.
In your example
When you write struct Bar<T: Foo> you want T to be of the kind * -> *, meaning: you can give one type to T and receive a simple type. But as I said, this is not yet expressible in Rust. To use a similar syntax, one might imagine that this could work in the future:
// This does NOT WORK!
struct Bar<for<U> T> where T<U>: Foo {
a: T<A>,
b: T<B>,
}
The for<> syntax is borrowed from "higher-ranked trait bounds" (HRTB), which can be used today for abstracting over lifetimes (most commonly used with closures).
Links
In case you want to read more about this topic, here are some links:
Niko Matsakis' great series of blog posts discussing one possible solution (associated type constructors) to the HKT problem
The RFC proposing generic associated types (just a less scary name for "associated type constructors")
HRTB explanation
Bonus: the solution to your problem in case associated type constructors will be implemented (I think, as there is no way to test)!
We have to take a detour in our implementation since the RFC wouldn't allow to pass Rc as a type parameter directly. It doesn't introduce HKTs directly, so to speak. But as Niko argues in his blog post, we can have the same flexibility and power as HKTs with associated type constructors by using so called "family traits".
/// This trait will be implemented for marker types, which serve as
/// kind of a proxy to get the real type.
trait RefCountedFamily {
/// An associated type constructor. `Ptr` is a type constructor, because
/// it is generic over another type (kind * -> *).
type Ptr<T>;
}
struct RcFamily;
impl RefCountedFamily for RcFamily {
/// In this implementation we say that the type constructor to construct
/// the pointer type is `Rc`.
type Ptr<T> = Rc<T>;
}
struct ArcFamily;
impl RefCountedFamily for ArcFamily {
type Ptr<T> = Arc<T>;
}
struct Graph<P: RefCountedFamily> {
// Here we use the type constructor to build our types
nodes: P::Ptr<Node>,
edges: P::Ptr<Edge>,
}
// Using the type is a bit awkward though:
type MultiThreadedGraph = Graph<ArcFamily>;
For more information, you should really read Niko's blog posts. Difficult topics explained well enough, that even I can understand them more or less!
EDIT: I just noticed that Niko actually used the Arc/Rc example in his blog post! I totally forgot that and thought of the code above myself... but maybe my subconscious still remembered, as I choose a few names exactly as Niko did. Anyway, here is his (probably way better) take on the issue.
In a way Rust does have what looks a lot like HKT (see Lukas's answer for a good description of what they are), though with some arguably awkward syntax.
First, you need to define the interface for the pointer type you want, which can be done using a generic trait. For example:
trait SharedPointer<T>: Clone {
fn new(v: T) -> Self;
// more, eg: fn get(&self) -> &T;
}
Plus a generic trait which defines an associated type which is the type you really want, which must implement your interface:
trait Param<T> {
type Pointer: SharedPointer<T>;
}
Next, we implement that interface for the types we're interested in:
impl<T> SharedPointer<T> for Rc<T> {
fn new(v: T) -> Self {
Rc::new(v)
}
}
impl<T> SharedPointer<T> for Arc<T> {
fn new(v: T) -> Self {
Arc::new(v)
}
}
And define some dummy types which implement the Param trait above. This is the key part; we can have one type (RcParam) which implements Param<T> for any T, including being able to supply a type, which means we're simulating a higher-kinded type.
struct RcParam;
struct ArcParam;
impl<T> Param<T> for RcParam {
type Pointer = Rc<T>;
}
impl<T> Param<T> for ArcParam {
type Pointer = Arc<T>;
}
And finally we can use it:
struct A;
struct B;
struct Foo<P: Param<A> + Param<B>> {
a: <P as Param<A>>::Pointer,
b: <P as Param<B>>::Pointer,
}
impl<P: Param<A> + Param<B>> Foo<P> {
fn new(a: A, b: B) -> Foo<P> {
Foo {
a: <P as Param<A>>::Pointer::new(a),
b: <P as Param<B>>::Pointer::new(b),
}
}
}
fn main() {
// Look ma, we're using a generic smart pointer type!
let foo = Foo::<RcParam>::new(A, B);
let afoo = Foo::<ArcParam>::new(A, B);
}
Playground

C++ Dynamic Dispatch Function

I'm trying to create an overloaded function that will be called with the dynamic type of an object. I try to do this without interfering with the actual class structure underneath, as I don't have direct access (i.e. I cannot add virtual methods, etc.)
As a concrete example, let's think of an AST class structure that looks somewhat like this:
class ASTNode {}; // this one is fully abstract; i.e. there's a virtual void method() = 0;
class Assignment : ASTNode {};
class Expression : ASTNode {};
class StringExpr : Expression {};
class MathExpr : Expression {};
I want to write a function act that will take an instance of ASTNode as parameter and, depending on its actual dynamic type do something different.
The call will be something like this
std::shared_ptr<ASTNode> parsedAST = get_a_parsed_ASTNode(); // ... received from some parser or library
act(parsedAST);
Then, I want to act, depending on the dynamic type of the ASTNode.
void act(std::shared_ptr<MathExpr> expr)
{
// Do something with Math expressions, e.g. evaluate their value
};
void act(std::shared_ptr<StringExpr> expr)
{
// Do something with String expressions, e.g. write their value to the log
};
void act(std::shared_ptr<Expression> expr)
{
// do something with other types of expressions (e.g. Boolean expressions)
};
Currently though, I cannot call since they dynamic type will be maybe not the ``most concrete type''. Instead, I have to manually create a dispatcher manually as follows, but the method is a bit silly in my opinion, since it does literally nothing else but dispatch.
void act(std::shared_ptr<ASTNode> node_ptr)
{
if(std::shared_ptr<MathExpr> derived_ptr = std::dynamic_pointer_cast<MathExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<StringExpr> derived_ptr = std::dynamic_pointer_cast<StringExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<Expression> derived_ptr = std::dynamic_pointer_cast<Expression>(node_ptr))
{
// do something with generic expressions. Make sure that this is AFTER the more concrete if casts
}
else if( ... ) // more of this
{
}
// more else if
else
{
// default action or raise invalid argument exception or so...
}
};
This is especially annoying & error-prone since my class hierarchy has many (> 20) different concrete classes that can be instantiated. Also, I have various act-functions, and when I refactor things (e.g. add an act for an additional type), I have to make sure to pay attention to the correct order of if(dynamic_pointer_cast) within the dispatcher.
Also it's not that stable, since a change in the underlying class hierarchy will require me to change every dispatcher directly, rather than just the specific act functions.
Is there a better / smarter solution? Evidently I'd appreciate "native" solutions, but I'm willing to consider libraries too.
Never encountered such problem myself, but can think of the following solution.
Create you hierarchy that mimics original hierarchy, has virtual act, the base has base pointer, and each cast it to the corresponding derived pointer.
Now, to create the needed wrapper, you don't need properly ordered dynamic_cast, dispach on typeid string. So your dispatch is a map from string to wrapper factory.
Sure you need RTTI for typeid string, but you would need it for dynamic_cast as well.

DLang - Template constraints - type must implement interface

I'm trying to convert the following C# code in to D, however I can't figure out how to make the template constraints work.
C# Implementation
public interface IComponent
{
}
public class Container
{
public T CreateComponent<T>() where T: IComponent, new()
{
// Trivial initialisation for example
var t = new T();
return t;
}
}
D Implementaiton
public interface Component
{
}
public class Container
{
public T createComponent(T)()
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
How can I re-create the "where T: IComponent" constraint?
I've tried various expressions combining is, typeof etc. but can't find anything that works.
Well, if all you're trying to do is require that T implement the interface IComponent, then is(T : IComponent) will test that T is implicitly convertible to IComponent (which is the case when IComponent is a base class of T or an interface that it implements). So, you'd end up with something like
public class Container
{
public T createComponent(T)()
if(is(T : IComponent))
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
Now, technically, other stuff can match if alias this is used to define an implicit conversion, which isn't likely to be common, but if you're being more paranoid about it, you could make the constraint also check that T is class - is(T == class).
public class Container
{
public T createComponent(T)()
if(is(T == class) && is(T : IComponent))
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
Then, T must be a class, and it must implicitly convert to IComponent. However, it is still technically possible for T to be a class which doesn't implement IComponent but does define an alias this which converts to an IComponent (it's just no longer possible for T to be a struct which does that). So, it's not perfect, but I don't know of a way to ensure that an implicit conversion is done via inheritance rather than alias this. So, unfortunately, I don't know of a way to absolutely guarantee that T is a class which implements IComponent. The most that I know how to do is to ensure that it implicitly converts to an `IComponent, which almost always means that it implements it.
However, the reality of the matter is that in the vast majority of cases, simply checking is(T : IComponent) is plenty, and depending on how your code is written, it might even work with a type which implicitly converts to IComponent but isn't actually an IComponent. So, the fact that alias this throws a spanner in the works may not actually be a problem. However, in general, alias this is a bane of generic code and why most generic code shouldn't be checking for implicit conversions. It's far too easy for a type to implicitly convert via alias this but not actually be converted in the function, in which case, it either won't compile, or it could have strange behavior if it supports the same operations that the target type does but those operations don't have the same results as they would if the original type were actually converted to the target type. So, if you actually want implicit conversions in templated code, you should force the implicit conversion by assigning the argument to the target type. But since you're looking to test for an interface rather than implicit conversions in general, what you probably want is a test which tests for that without allowing implicit conversions via alias this. Unfortunately, the only way that I know of to check at compile time whether one type derives from another or implements a specific interface is to check whether it implicitly converts to that base class or interface.
But maybe there's some fun voodoo with traits that's actually able to do it. If there is, we should probably add something to std.traits which does that for you, and if there isn't, maybe we should find a way to add it, since alias this can definitely be annoying if you don't want it. But fortunately, it's not a problem that comes up in most code, and if you're not writing a public API, then you only have to worry about it if you're declaring types with alias this. If you're not, then it really doesn't matter.
You don't even need a template constraint, just a template specialization:
T createComponent(T : IComponent)() { /* some code */ }
In typical fashion I found the answer moments after asking here http://ddili.org/ders/d.en/is_expr.html
public T addComponent(T)()
if (is(T: Component))

Syntax clarification

I was browsing some of Ubuntu's Mir examples and i stumbled upon code that i couldn't understand.
struct DemoServerConfiguration : mir::DefaultServerConfiguration
{
What is going on here ": mir::DefaultServerConfiguration"?
Inside that struct there's this
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
{
return shell_placement_strategy(
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
});
}
Same story here, i don't understand the syntax the unclear parts are:
<msh::PlacementStrategy> the_shell_placement_strategy()
and
return shell_placement_strategy(
[this]
{
Inside the same struct again
std::initializer_list<std::shared_ptr<mi::EventFilter> const> the_event_filters() override
{
return filter_list;
}
Why the multiple <> <> <> nested? Why the the_event_filters() there?
And the last piece
mir::run_mir(config, [&config, &wm](mir::DisplayServer&)
{
code
});
Unclear part
(config, [&config, &wm](mir::DisplayServer&)
);
First example
That's simply a case of inheriting from an internal type:
class C
{
public:
class Internal
{
};
};
class D : public C::Internal
{
// D derives from Internal class, which is a member of C class
};
The :: is an operator of scope resolution. The expression A::B means: "B, which is a member of A". :: works for classes, structures and namespaces.
Second example
That's a little bit more complicated.
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
{
return shell_placement_strategy(
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
});
}
Let's break it to parts.
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
This is a function / method the_shell_placement_strategy, which returns a result of type std::shared_ptr (generic class parametrized with msh::PlacementStrategy - see previous point).
return shell_placement_strategy(
It returns result of calling the shell_placement_strategy...
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
}
...which takes a lambda (nameless function) as a parameter. That nameless function wants to have access to this (thus [this]) and returns result of call to generic function std::make_shared, parametrized with me::FulscreenPlacementStrategy and called with parameter being a result of calling the_display() method / function.
You may read about lambdas elsewhere, but I'll include a short explanation for reference:
[access-specification](parameters){ body }
Where:
access-specification defines the relation between lambda and local variables. For example, [a] means, that lambda will have access to local variable a by value; [&a] - the same, but by reference; [&] - lambda will have access to all local variables by reference and so on.
parameters - regular definition of function parameters
body - regular body of lambda.
The lambda notation is a part of C++11 standard.
Last example
You now should be able to interpret this example:
mir::run_mir(config, [&config, &wm](mir::DisplayServer&)
{
code
});
Thats:
A call to run_mir method (or function), which is a part of mir class (or namespace);
With two parameters: config and a function, which accepts two parameters;
config is passed as first parameter;
A lambda is passed by the second parameter.
Now the lambda:
It wants to access by reference two local variables: config and wm
It accepts one parameter of type mir::DisplayServer& (there's no name for this parameter, so it seems, that it does not actually use it
It does <code> :)
First case, it is private inheritance. DemoServerConfiguration is derived from mir::DefaultServerConfiguration, where mir is probably a namespace (but could also be a class that declares the inner class DefaultServerConfiguration.
Second case, you are looking at lambda expression definition. You can read some introduction here.
Finally, the initializer lists are actually another feature introduced in C++11 standard (not yet supported by most of the compilers, AFAIK). Some introduction about them here.
mir::DefaultServerConfiguration
Here mir could be a namespace or a class inside which DefaultServerConfiguration is defined. So for example, it could be this:
namespace mir
{
class DefaultServerConfiguration
{
/*...*/
};
}
Or this,
class mir
{
public:
class DefaultServerConfiguration
{
/*...*/
};
}
In both cases, you could access the class DefaultServerConfiguration as:
mir::DefaultServerConfiguration
The same is true for other cases.
struct DemoServerConfiguration : mir::DefaultServerConfiguration
{
Here DemoServerConfiguration is a class deriving from mir::DefaultServerConfiguration. Make sense?
You also notice this in case of std::make_shared. Here std is a namespace defined by C++ Standard Library inside which the library defines make_shared function template.
Hope that helps.

template query, accessing private member

I am referring to one of the exercises mentioned in the book "thinking in c++.
Below code snippet throws an error for the call h.play, which i understand, because
the member i is private. But I was expecting the same error for the call me.play. If i comment the call h.play the code compiles fine. Why there is no error for the call me.play ?
class Buddy {};
template<class T> class My {
int i;
public:
void play(My<Buddy>& s) {
s.i = 3;
}
};
int main() {
My<int> h;
My<Buddy> me, bud;
h.play(bud);
me.play(bud);
}
Thankyou.
[Edit] Is there a way to see what code the compiler has generated for
My<int> h and
My<Buddy> me
? (anything similar to -E compiler flag) ?
Members are always "public" to instances of another object with the same type.
Meaning a My<Buddy> instance (such as me) can access private members of another My<Buddy> instance (such as bud).
Keep in mind that My<int> is a completely different type than My<Buddy>, and so it cannot access those members.
Because the play method is defined as taking a reference to My<Buddy> rather than a My<T>, the effective class is the same type when called on another instance of My<Buddy>. Therefore private members are accessible.
Unlike in languages that just pretend to have strong static type system and generics (looking at you Java), C++ allows you to disambiguate statically parametric types (template types) based on the parameters (the parameters being usually types) the types are templated on.
Note: You can also use a derived (dynamically / late bound) type as a parameter for a statically parametrized type, but it's not relevant in this scenario.
In other words, in C++:
typeid(me) == typeid(bud) will be TRUE
typeid(h) == typeid(me) will be FALSE
even though the type "My" is the same.
You can access the private data-members from the same type as though they were public, but as you can see, the second comparison is false because the operands are not of the same type, therefore you violate the access restrictions of the type.
Also, I don't think there is any way to take a look at the compiler-generated code. (As far as I know.)