Can I implement operator overloading for D's SumType alias? - templates

TLDR: Is there a way make D's SumType play nice with opCmp while maintaining its functionality?
Context
I'm writing a program for which D's native SumType works almost completely. However, I would like to be able to do the following:
alias Foo = SumType!(int, string);
Foo x = 3;
Foo y = 5;
writeln(max(x, y));
However, since no ordering is natively defined for SumType, I receive the following error:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm\comparison.d(1644): Error: static assert: "Invalid arguments: Cannot compare types SumType!(int, string) and SumType!(int, string) for ordering."
mwe.d(11): instantiated from here: `max!(SumType!(int, string), SumType!(int, string))`
I was able to remedy this specific issue using the following method:
import std.stdio : writeln;
import std.exception : assertThrown;
import std.algorithm.comparison : max;
import core.exception : AssertError;
import std.sumtype;
struct Foo {
SumType!(int, string) value;
this(T)(T v) {
value = v;
}
ref Atom opAssign(T)(T rhs) {
value = rhs;
return this;
}
int opCmp(Foo other) {
return match!(
(a, b) => a < b ? -1 : a == b ? 0 : 1,
(_1, _2) => assert(0, "Cannot match")
)(value, other.value);
}
}
void main() {
Foo x = 3;
Foo y = 7;
Foo z = "asdf";
assert(x < y); // comparing ints works correctly
assertThrown!AssertError(x < z); // cannot compare int and string
assert(max(x, y) == y); // D's max works
}
The Problem
While I can now use x.value.match!(...) where I used to use x.match!(...), I would like to still be able to call .match! directly on x, and also use match!(...)(x, y) instead of match!(...)(x.value, y.value). I do not like the idea of inserting hundreds of .value throughout my code just to make certain functions like max work, and would prefer if there were a more elegant solution. I tried tinkering around with defining a custom opDispatch using mixins but I couldn't get that to play nicely with the existing SumType:
struct Foo {
SumType!(int, string) value;
this(T)(T v) {
value = v;
}
ref Atom opAssign(T)(T rhs) {
value = rhs;
return this;
}
int opCmp(Foo other) {
return match!(
(a, b) => a < b ? -1 : a == b ? 0 : 1,
(_1, _2) => assert(0, "Cannot match")
)(value, other.value);
}
auto opDispatch(string name, T...)(T vals) {
return mixin("value." ~ name)(vals);
}
}
void main() {
Foo y = 7;
y.match!(
(int intValue) => writeln("Received an integer"),
(string strValue) => writeln("Received a string")
);
}
And I am unable to decode the error which results:
mwe.d(38): Error: none of the overloads of template `std.sumtype.match!(function (int intValue) #safe
{
writeln("Received an integer");
return ;
}
, function (string strValue) #safe
{
writeln("Received a string");
return ;
}
).match` are callable using argument types `!()(Foo)`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\sumtype.d(1659): Candidate is: `match(SumTypes...)(auto ref SumTypes args)`
with `SumTypes = (Foo)`
must satisfy the following constraint:
` allSatisfy!(isSumType, SumTypes)`
Beyond that I am out of ideas as to how to find a less clunky solution.

I suggest giving alias this a try. Similar to class inheritance, this lets you specialize a type and let other things fall back to the original member.
import std.stdio : writeln;
import std.exception : assertThrown;
import std.algorithm.comparison : max;
import core.exception : AssertError;
import std.sumtype;
struct Foo {
SumType!(int, string) value;
this(T)(T v) {
value = v;
}
int opCmp(Foo other) {
return match!(
(a, b) => a < b ? -1 : a == b ? 0 : 1,
(_1, _2) => assert(0, "Cannot match")
)(value, other.value);
}
alias value this;
}
void main() {
Foo x = 3;
Foo y = 7;
Foo z = "asdf";
assert(x < y); // comparing ints works correctly
assertThrown!AssertError(x < z); // cannot compare int and string
assert(max(x, y) == y); // D's max works
// this will now automatically fall back to y.value.match
y.match!(
(int intValue) => writeln("Received an integer"),
(string strValue) => writeln("Received a string")
);
}
See, you still must construct your special type, but then after that, it will look up there for members. It will find the opCmp, letting it extend the type. But then for everything else, since it isn't there, it will try checking obj.value instead, falling back to the original type.
This doesn't always work, and it means it will implicitly convert too, meaning you can pass a Foo to a void thing(SumType!(int, string)) with it passing foo.value to the function, which may or may not be desirable.
But I think it is the closest thing to what you want here.
(note btw why you got an error originally is that match isn't actually a member of SumType. it is an outside free function that takes all the match lambdas as template arguments. An opDispatch could forward template arguments too - it can be done in a two-level definition - but since match is not a member anyway, it isn't quite going to solve things anyway whereas the alias this does seem to work)

Related

Find neighbor of target in BTreeMap (or any other treemap) in rust

How to efficiently implement below c++ function in rust? The data structure must be tree based (BTree, RBTree, etc).
Given a sorted map m, a key target, and a value val.
Find the lower_bound entry (the first key >= target). return DEFAULT if no such entry.
If the value of the found entry <= val and it has previous entry, return value of previous entry.
If the value of the found entry > val and it has next entry, return value of the next entry.
Otherwise, return the found value.
template<class K, class V>
V find_neighbor(const std::map<K, V>& m, const K& target, const V& val) {
auto it = m.lower_bound(target);
if( it == m.end() ) return V{}; // DEFAULT value.
if( it->second <= val && it != m.begin() )
return (--it)->value; // return previous value
if( it->second > val && it != (--m.end()) )
return (++it)->value; // return next value
return it->second; // return target value
}
Thats what I've got.
Create trait FindNeighbor that adds the function find_neighbor to all BTreeMaps
I'm quite confused what the algorithm does, though, tbh. But it should (tm) behave identical to the C++ version.
If you use this in an actual project though, for the love of god, please write unit tests for it. 😄
use std::{borrow::Borrow, collections::BTreeMap};
trait FindNeighbor<K, V> {
type Output;
fn find_neighbor(&self, target: K, val: V) -> Self::Output;
}
impl<K, V, KI, VI> FindNeighbor<K, V> for BTreeMap<KI, VI>
where
K: Borrow<KI>,
V: Borrow<VI>,
KI: Ord,
VI: Default + PartialOrd + Clone,
{
type Output = VI;
fn find_neighbor(&self, target: K, val: V) -> VI {
let val: &VI = val.borrow();
let target: &KI = target.borrow();
let mut it = self.range(target..);
match it.next() {
None => VI::default(),
Some((_, it_value)) => {
if it_value <= val {
match self.range(..target).rev().next() {
Some((_, prev_val)) => prev_val.clone(),
None => it_value.clone(),
}
} else {
match it.next() {
Some((_, next_val)) => next_val.clone(),
None => it_value.clone(),
}
}
}
}
}
}
fn main() {
let map = BTreeMap::from([(1, 5), (2, 3), (3, 8)]);
println!("{:?}", map.find_neighbor(3, 10));
}
3
Note a couple of differences between C++ and Rust:
Note that there are trait annotations on the generic parameters. Generic functions work a little different than C++ templates. All the capabilities that get used inside of a generic method have to be annotated as trait capabilities. The advantage is that generics are then guaranteed to work with every type they take, no random compiler errors can occur any more. (C++ templates are more like duck-typing, while Rust generics are strongly typed)
We implement a trait that adds new functionality to an external struct. That is something that also doesn't exist in C++, and tbh I really like this mechanic in Rust.

Function overloaded by bool and enum type is not differentiated while called using multiple ternary operator in C++

Got into an interesting problem while tried to call the overloaded function using conditional operator (just to avoid multiple if else condition)
class VirtualGpio
{
typedef enum
{
OUTPUT = 0xC7,
INPUT ,
DIRINVALID
}GpioDirection;
struct pinconfig
{
struct pinmap pin;
GpioPolarity plrty;
bool IsPullupCfgValid;
bool IsTriStCfgValid;
bool IsInputFilterValid;
GpioDirection dic;
gpiolistner fptr; // Callback function pointer on event change
};
};
class factory
{
public:
VirtualGpio *GetGpiofactory(VirtualGpio::pinconfig *cfg,VirtualGpio::GpioAccessTyp acc=VirtualGpio::Pin);
private:
int setCfgSetting(VirtualGpio::pinmap * const getpin, VirtualGpio::GpioDirection const data);
int setCfgSetting(VirtualGpio::pinmap * const getpin, bool const data);
};
int factory::setCfgSetting(VirtualGpio::pinmap * const getpin, VirtualGpio::GpioDirection const data)
{
cout << "It is a Direction overloaded" << endl;
}
int factory::setCfgSetting(VirtualGpio::pinmap * const getpin, bool const data)
{
cout << "It is a bool overloaded" << endl;
}
VirtualGpio* factory::GetGpiofactory(VirtualGpio::pinconfig *cfg,VirtualGpio::GpioAccessTyp acc)
{
VirtualGpio * io = new VirtualGpio();
printf("acc : 0x%X, pin : 0x%x, port : 0x%x\n",acc, cfg->pin.pinno, cfg->pin.portno);
printf("value of expression : 0x%x\n",((acc == VirtualGpio::Pin)? cfg->dic : ((cfg->dic == VirtualGpio::INPUT)?true :false))); <= this prints the right value
if(acc == VirtualGpio::Pin)
setCfgSetting(&cfg->pin,cfg->dic);
else if(cfg->dic == VirtualGpio::INPUT)
setCfgSetting(&cfg->pin,true);
else
setCfgSetting(&cfg->pin,false);
#if 0
if(setCfgSetting(&cfg->pin, ((acc == VirtualGpio::Pin)? cfg->dic : ((cfg->dic == VirtualGpio::INPUT)?true :false))) == ERROR)
{
printf("Error Setting the IO configuration for XRA\n");
}
else
printf("Set IO config successfully\n");
#endif
return io;
}
The commented part #if 0 in GetGpiofactory() is same as the above
multiple if-else-if-else block, but if I uncomment the #if0 part to #if
1, for all the possible inputs only bool version of the overloaded
function i.e setCfgSetting(VirtualGpio::pinmap * const getpin, bool
const data) is invoked.
below is my main code.
main()
{
static struct VirtualGpio::pinconfig cfg = {
.pin = {
.location = VirtualGpio::GPIO_ON_GPIOEXP1_TCI,
.pinno = 0,
.portno = -1
},
.plrty = VirtualGpio::active_high,
.IsPullupCfgValid = true,
.IsTriStCfgValid = true,
.IsInputFilterValid = true,
.dic = VirtualGpio::OUTPUT,
.fptr = NULL
};
factory fac;
fac.GetGpiofactory(&cfg);
}
Surprised, the overloaded function works well if I don't use the ternary operator instead use multiple if-else if-else blocks. curious to understand the reason.
That is because the ternary operator always evaluates to a single type. You can't "return" different types with this operator.
When the compiler encounters such an expression he tries to figure out whether he can reduce the whole thing to one type. If that's not possible you get a compile error.
In your case there is a valid option using bool as a type. Because cfg->dic is an enum type which is implicitly convertible to bool. If you would use and enum class your code would not compile anymore showing you what your actual problem is (example).
Also I don't really see what the advantage of this kind of code is. In my opinion it makes the code much harder to read. You could reduce your ifs to just one, if you're concerned about too many of them:
if(acc == VirtualGpio::Pin)
setCfgSetting(&cfg->pin,cfg->dic);
else
setCfgSetting(&cfg->pin, cfg->dic == VirtualGpio::INPUT);

Get the variable values at runtime using reflection in Dlang

Is it possible to get the class/struct/other variables value during runtime in dlang to get/set its value? If yes how to do that please provide example.
And also is it possible to get the runtime variable value?
Ex:
class S{ int svariable = 5;}
class B { int bvariable = 10;}
void printValue(T, T instanceVariable, string variableName) {
writeln("Value of ", variableName, "=", instanceVariable.variableName);
}
Output:
Value of svariable = 5;
Value of bvariable = 10;
There is a library named witchcraft that allows for runtime reflection. There are examples of how to use it on that page.
I'd first recommend trying a reflection library like #mitch_ mentioned. However, if you want to do without an external library, you can use getMember to get and set fields as well as invoke functions:
struct S {
int i;
int fun(int val) { return val * 2; }
}
unittest {
S s;
__traits(getMember, s, "i") = 5; // set a field
assert(__traits(getMember, s, "i") == 5); // get a field
assert(__traits(getMember, s, "fun")(12) == 24); // call a method
}

C++ sharing array elements across modules with const-ness for few fields only

This is sort of a design doubt .
Scenario: I have an array which contain some integer elements . This array is populated by 1 module (.so) in my code base say X. It is then shared to another module say Y (.so) . At run time X module identifies that module Y would need to work on few fields of the array and modify it and that was the reason X shared the array to Y . ( Both these so are consumed into one binary .)
Once Y returns the module X prints the array .
Problem : How can I enforce programatically that module Y does not modify any other array index other than the one identified by X . SInce the whole array is passed between modules i cant make it const as then Y would not be able to change any field . You can say i want to enforce const-ness for few fields identified at run time .
How about this:
template <class T> class CProtectedArray {
private:
T* m_aItems;
unsigned int* m_aMask;
public:
CProtectedArray(int cElem, bool fInitialProtect) : m_aItems(NULL) {
int cbElem = sizeof(T)*cElem;
int cbMask = sizeof(int)*(cElem+31)/32;
m_aItems = (T*)malloc(cbElem + cbMask);
m_aMask = (unsigned int*)(m_aItems + cElem);
memset(m_aItems, 0, cbElem);
memset(m_aMask, fInitialProtect ? -1 : 0, cbMask);
}
~CProtectedArray() {
if (m_aItems)
free(m_aItems);
}
bool IsProtected(int iItem) { return !!(m_aMask[iItem>>5] & (1<<(iItem&31))); }
void Protect(int iItem) { m_aMask[iItem>>5] |= 1<<(iItem&31); }
void UnProtect(int iItem) { m_aMask[iItem>>5] &= ~(1<<(iItem&31)); }
void Set(int iItem, T val) {
if (!IsProtected(iItem))
m_aItems[iItem] = val;
}
};
int main(int argc, char* argv[])
{
CProtectedArray<int> A(100, true);
bool f = A.IsProtected(30); // f = true
A.Set(30, 23); // nothing happens
A.UnProtect(30);
f = A.IsProtected(30); // f = false
A.Set(30, 24); // sets element 30 to 24
A.Protect(30);
f = A.IsProtected(30); // f = true
A.Set(30, 25); // nothing happens
}

Get Max value from List<myType>

I have List List<MyType>, my type contains Age and RandomID
Now I want to find the maximum age from this list.
What is the simplest and most efficient way?
Assuming you have access to LINQ, and Age is an int (you may also try var maxAge - it is more likely to compile):
int maxAge = myTypes.Max(t => t.Age);
If you also need the RandomID (or the whole object), a quick solution is to use MaxBy from MoreLinq
MyType oldest = myTypes.MaxBy(t => t.Age);
Okay, so if you don't have LINQ, you could hard-code it:
public int FindMaxAge(List<MyType> list)
{
if (list.Count == 0)
{
throw new InvalidOperationException("Empty list");
}
int maxAge = int.MinValue;
foreach (MyType type in list)
{
if (type.Age > maxAge)
{
maxAge = type.Age;
}
}
return maxAge;
}
Or you could write a more general version, reusable across lots of list types:
public int FindMaxValue<T>(List<T> list, Converter<T, int> projection)
{
if (list.Count == 0)
{
throw new InvalidOperationException("Empty list");
}
int maxValue = int.MinValue;
foreach (T item in list)
{
int value = projection(item);
if (value > maxValue)
{
maxValue = value;
}
}
return maxValue;
}
You can use this with:
// C# 2
int maxAge = FindMaxValue(list, delegate(MyType x) { return x.Age; });
// C# 3
int maxAge = FindMaxValue(list, x => x.Age);
Or you could use LINQBridge :)
In each case, you can return the if block with a simple call to Math.Max if you want. For example:
foreach (T item in list)
{
maxValue = Math.Max(maxValue, projection(item));
}
int max = myList.Max(r => r.Age);
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.max.aspx
var maxAge = list.Max(x => x.Age);
thelist.Max(e => e.age);
Easiest way is to use System.Linq as previously described
using System.Linq;
public int GetHighestValue(List<MyTypes> list)
{
return list.Count > 0 ? list.Max(t => t.Age) : 0; //could also return -1
}
This is also possible with a Dictionary
using System.Linq;
public int GetHighestValue(Dictionary<MyTypes, OtherType> obj)
{
return obj.Count > 0 ? obj.Max(t => t.Key.Age) : 0; //could also return -1
}
Simplest is actually just Age.Max(), you don't need any more code.
How about this way:
List<int> myList = new List<int>(){1, 2, 3, 4}; //or any other type
myList.Sort();
int greatestValue = myList[ myList.Count - 1 ];
You basically let the Sort() method to do the job for you instead of writing your own method. Unless you don't want to sort your collection.