Signature for Object.assign in typescript? - typescript1.7

What's the correct signature for Object.assign in typescript?
We've implemented a jquery-like #extend function (similar to Object.assign).
Unfortunately, the compiler doesn't recognize the extended object.
function extend<T>(dst : Object, ...src : Object[]) : T { //... }
const data = extend({}, {foo: 'foo'});
data.foo //compiler error

As per https://github.com/Microsoft/TypeScript/blob/master/src/lib/es6.d.ts, this is the declaration for Object.assign:
assign<T, U>(target: T, source: U): T & U;
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
assign(target: any, ...sources: any[]): any;
So the implementation for #extend would look something like this:
function extend<T, U>(target: T, source: U): T & U;
function extend<T, U, V>(target: T, source1: U, source2: V): T & U & V;
function extend<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
function extend(target: any, ...sources: any[]): any {
//implementation
}
However if es6.d.ts exists, then that begs the question of whether or not we should be using that instead of a custom #extend..

You can also use casting:
(<any>Object).assign(this.success, success.json())

Related

Why can a std::tuple not be assigned with an initializer list?

I wonder why this choice is made. It would allow to write many functions in a very clear and neat way.. for instance:
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = { b, a };
while (b > 0)
std::tie(a, b) = { b, a % b };
return a;
}
std::initializer_list is a homogeneous collection of items, while std::tuple is heterogeneous. The only case where it makes sense to define a std::tuple::operator= for std::initializer_list is when the tuple is homogeneous and has the same size as the initializer list, which is a rare occurrence.
(Additional information in this question.)
Solution/workaround: you can use std::make_tuple instead:
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = std::make_tuple(b, a);
while (b > 0)
std::tie(a, b) = std::make_tuple(b, a % b);
return a;
}
...or std::tuple's constructor in C++17 (thanks to Template argument deduction for class templates):
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = std::tuple{b, a};
while (b > 0)
std::tie(a, b) = std::tuple{b, a % b};
return a;
}
Why does
std::tie(a,b) = {b, a};
not compile?
{} on the right hand side of an assignment can only call a non-explicit constructor of an argument of operator=.
The operator= overloads available are:
tuple& operator=( const tuple& other );
tuple& operator=( tuple&& other );
template< class... UTypes >
tuple& operator=( const tuple<UTypes...>& other );
template< class... UTypes >
tuple& operator=( tuple<UTypes...>&& other );
template< class U1, class U2 >
tuple& operator=( const pair<U1,U2>& p );
template< class U1, class U2 >
tuple& operator=( pair<U1,U2>&& p );
The template operator overloads cannot deduce their types from {} (note: this may change in C++17), leaving:
tuple& operator=( const tuple& other );
tuple& operator=( tuple&& other );
where tuple is std::tuple<int&, int&> in this case.
The tuple constructor for tuple<Ts...> that perfect forwards element-wise construction is explicit (#3 on that list). {} will not call an explicit constructor.
The conditionally non-explicit constructor takes Ts const&...; it does not exist if the Ts are non-copyable, and int& is non-copyable.
So there are no viable types to construct from {int&, int&}, and overload resolution fails.
Why does the standard not fix this? Well, we can do it ourselves!
In order to fix this, we'd have to add a special (Ts...) non-explicit constructor to tuple that only exists if the Ts types are all references.
If we write a toy tuple:
struct toy {
std::tuple<int&, int&> data;
toy( int& a, int& b ):data(a,b) {} // note, non-explicit!
};
toy toy_tie( int& a, int& b ) { return {a,b}; }
and use it, you'll notice that
std::tie(a, b) = {b, a};
compiles and runs.
However,
std::tie(a, b) = { b, a % b };
does not, as a%b cannot be bound to int&.
We can then augment toy with:
template<class...>
toy& operator=( std::tuple<int, int> o ) {
data = o;
return *this;
}
(+ defaulted special member functions. template<class...> ensures it has lower priority than the special member functions, as it should).
This which lets assign-from {int,int}. We then run it and... get the wrong result. The gcd of 5,20 is 20. What went wrong?
toy_tie(a, b) = std::tie( b, a );
with both a and b bound to references is not safe code, and that is what
toy_tie(a, b) = { b, a };
does.
In short, doing this right is tricky. In this case, you need to take a copy of the right hand side before assigning to be safe. Knowing when to take a copy and when not to is also tricky.
Having this work implicitly looks error prone. So it is, in a sense, accidental that it doesn't work, but fixing it (while possible) looks like a bad idea.
live example.

Unique set of undirected edges

I want to create a set (mathematically speaking, not std::set) of unique elements in C++. My elements are std::pair<int, int> and they represent an edge. Because those edges are not directed, I don't want to have duplicates like (3,4) and (4,3). How can I achieve this in C++ ?
Something along these lines, perhaps:
using Edge = std::pair<int, int>;
struct CompareEdges {
bool operator()(const Edge& a, const Edge& b) const {
return Normalize(a) < Normalize(b);
}
private:
Edge Normalize(const Edge& e) {
if (e.first <= e.second) return e;
return {e.second, e.first};
}
};
std::set<Edge, CompareEdges> SetOfEdges;
This is another solution, with the compare function as lambda expression.
using Edge = pair<int, int>;
std::set<Edge, std::function<bool(const Edge &, const Edge &)>> edges(
[](const Edge &a, const Edge &b)
{
const int x = min(a.first, a.second);
const int y = min(b.first, b.second);
if (x < y)
return true;
else if (y > x)
return false;
else
return max(a.first, a.second) < max(b.first, b.second);
}
);

Is it possible in C++11 to combine functions into a new function?

This is more a kind of theoretical question. Is it possible in C++11 to combine functions into a new function? For example :
auto f = [](int i){return i * 2;};
auto g = [](int i){return i + 10;};
So this works:
auto c = f(g(20)); // = 60
But I want an object that stores the combination, like
auto c = f(g);
std::cout << c(20) << std::endl; //prints 60
Edit:
Additionally what i want to create is a function a, which you can give a function b and an int n, and which returns the n'th combination of the given function b. For example (not compilable)
template<typename T>
auto combine(T b, int i) -> decltype(T)
{
if (i == 0)
return b;
return combine(b, i - 1);
}
auto c = combine(f, 2); //c = f(f(f(int)))
A first attempt:
template<class First, class Second>
auto compose( Second&& second, First&& first ) }
return [second = std::forward<Second>(second), first=std::forward<First>(first)]
(auto&&...args)->decltype(auto) {
return second( first( decltype(args)(args)... ) );
};
}
template<class A, class B, class...Rest>
auto compose(A&& a, B&& b, Rest&&... rest) {
return compose( compose(std::forward<A>(a), std::forward<B>(b)), std::forward<Rest>(rest)... );
}
template<class A>
std::decay_t<A> compose(A&& a) {
return std::forward<A>(a);
}
in C++14. Now, this isn't perfect, as the pattern doesn't work all that well in C++.
To do this perfectly, we'd have to take a look at compositional programming. Here, functions interact with an abstract stack of arguments. Each function pops some number of arguments off the stack, then pops some number back on.
This would allow you do do this:
compose( print_coord, get_x, get_y )
where get_x and get_y consume nothing but return a coordinate, and print_coord takes two coordinates and prints them.
To emulate this in C++, we need some fancy machinery. Functions will return tuples (or tuple-likes?), and those values will be "pushed onto the argument stack" logically.
Functions will also consume things off this argument stack.
At each invocation, we unpack the current tuple of arguments, find the longest collection that the function can be called with, call it, get its return value, unpack it if it is a tuple, and then stick any such returned values back on the argument stack.
For this more advanced compose to compose with itself, it then needs SFINAE checks, and it needs to be able to take a invokable object and a tuple of arguments and find the right number of arguments to call the invokable object with, plus the left-over arguments.
This is a tricky bit of metaprogramming that I won't do here.
The second part, because I missed it the first time, looks like:
template<class F>
auto function_to_the_power( F&& f, unsigned count ) {
return [f=std::forward<F>(f),count](auto&& x)
-> std::decay_t< decltype( f(decltype(x)(x)) ) >
{
if (count == 0) return decltype(x)(x);
auto r = f(decltype(x)(x));
for (unsigned i = 1; i < count; ++i) {
r = f( std::move(r) );
}
return r;
};
}
This uses no type erasure.
Test code:
auto f = [](int x){ return x*3; };
auto fs = std::make_tuple(
function_to_the_power( f, 0 ),
function_to_the_power( f, 1 ),
function_to_the_power( f, 2 ),
function_to_the_power( f, 3 )
);
std::cout << std::get<0>(fs)(2) << "\n";
std::cout << std::get<1>(fs)(2) << "\n";
std::cout << std::get<2>(fs)(2) << "\n";
std::cout << std::get<3>(fs)(2) << "\n";
prints:
2
6
18
54
You can write something along the lines of:
#include <functional>
#include <iostream>
template<class F>
F compose(F f, F g)
{
return [=](int x) { return f(g(x)); };
}
int main()
{
std::function<int (int)> f = [](int i) { return i * 2; };
std::function<int (int)> g = [](int i) { return i + 10; };
auto c = compose(f, g);
std::cout << c(20) << '\n'; // prints 60
}
The code can be simply extended to cover the second half of the question:
template<class F>
F compose(F f, unsigned n)
{
auto g = f;
for (unsigned i = 0; i < n; ++i)
g = compose(g, f);
return g;
}
int main()
{
std::function<int (int)> h = [](int i) { return i * i; };
auto d = compose(h, 1);
auto e = compose(h, 2);
std::cout << d(3) << "\n" // prints 81
<< e(3) << "\n"; // prints 6561
}
NOTE. Here using std::function. It isn't a lambda but wraps a lambda with a performance cost.

Return type of wrapper function C++11

I have re-arranged an example regarding the std::forward with template.
I have used a wrapper function and everything is fine, if i declare it as void function. It works as expected.
#include<iostream>
using namespace std;
template <typename T, typename U>
auto summation(T const &a, U const& b) -> decltype(T{}, U{}) {
cout << "call by lvalue" << endl;
return a+b;
}
template <typename T, typename U>
auto summation(T&& a, U && b) -> decltype(T{},U{}) {
cout << "call by rvalue" << endl;
return a+b;
}
template<typename T,typename U> void func(T&& a, U && b) {
summation(forward<T>(a), forward<U>(b));
}
int main() {
int x = 10;
double y = 20;
func(x,y);
func(10,20);
}
but if I want to return a type from a wrapper function, no matter what I used, I got error on lvalues function call ONLY, fund(x,y), stating "....function does not match the arguments"... the other fund(10,20) works.
template<typename T,typename U> auto func(T&& a, U && b) -> decltype(T{}, U{}) {
return summation(forward<T>(a), forward<U>(b));
}
and even using c++14 decltype(auto) for deducing the return type of forwarding functions and similar wrappers
template<typename T,typename U> decltype(auto) func(T&& a, U && b) {
return summation(forward<T>(a), forward<U>(b));
}
it does not work either, stating "decline(type) is C++o1 extension..." that, thank you compiler, but it does help.
One non sense horrible solution is declare the return type or T or U as return type. This compiles even if I got a warning stating "Reference to stack memory associated to local variable returned"
template<typename T,typename U> U func(T&& a, U && b) {
auto res = summation(forward<T>(a), forward<U>(b));
return res;
}
the return type of std::forward given (t) the object to be forwarded is
static_cast<T&&>(t)
therefore it the first solution with auto should work but it does not.
Any suggestion on this ?
Thanks for any help
decltype means the type of the expression given in its argument. So
decltype(T {}, U {})
will be the type of the expression T{}, U{}. You have the comma operator here, and so the type of the expression is the type of the expression after the comma, which is U{}, hence decltype (T{}, U{}) gives you type U (more precisely, U &&, I guess, since it is an rvalue).
What you want is
decltype(T{} + U{})
or
decltype(a+b)
(thanks to Jonathan Wakely, see comments).

Basic operator overloading in D (Part 2)

Using Tango with D1:
class C
{
private int j;
public int opBinary(char[] op: "+") (ref C x) { return 1; }
public int opBinary(char[] op: "+") (C x) { return 3; }
}
int opBinary(char[] op: "+") (ref C x, ref C y) { return 2; }
int opBinary(char[] op: "+") (C x, C y) { return 2; }
void main() {
C a = new C;
C b = new C;
int j = a + b;
}
Compiler error:
"incompatible types"
meaning the overloaded operators weren't matched.
Can't wait to get the hang of D.
Thanks much.
OH Yea: I'm using Tango with D1, so maybe that's why it's not working? I'd like to stick with Tango. Has anyone used Tango + D2?
In D1 templated operator overloading using opBinary, etc. doesn't work. You need to use opAdd, opSub, etc.

Resources