I am trying to implement a TSortedMap with my custom struct as the key. I have overloaded the operators for the struct. However, when I try to compile I get this error at the line of code where I am adding an element to the TSortedMap:
error C2678: binary '<': no operator found which takes a left-hand operand of type 'const T'
(or there is no acceptable conversion)
My struct:
USTRUCT(BlueprintType)
struct FUtility
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(ClampMin = "0.0", ClampMax = "1.0"))
float value = 0.0f;
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta = (ClampMin = "0.0", ClampMax = "1.0"))
float weight = 1.0f;
FORCEINLINE bool operator== (const FUtility& other)
{
return this->value == other.value && this->weight == other.weight;
}
FORCEINLINE bool operator< (const FUtility& other)
{
return (this->value * this->weight) < (other.value * other.weight);
}
.....
friend uint32 GetTypeHash(const FUtility& other)
{
return GetTypeHash(other.value) + GetTypeHash(other.weight);
}
};
Not quite sure why it is not compiling since it is overloaded. Maybe it isn't overloaded correctly. Any help would be greatly appreciated.
Well, oddly enough I figured it out. It was really bugging me that all of the operator logic in the documentation took two parameters. It turns out I was just missing the friend keyword. From there I was able to add the second parameter and it compiled nicely.
Example:
friend bool operator< (const FUtility& a, const FUtility& b)
{
return (a.value * a.weight) < (b.value * b.weight);
}
I was wondering how I could change the code below such the bmBc is computed at compile time . The one below works for runtime but it is not ideal since I need to know the bmBc table at compile-time . I could appreciate advice on how I could improve on this.
import std.conv:to;
import std.stdio;
int [string] bmBc;
immutable string pattern = "GCAGAGAG";
const int size = to!int(pattern.length);
struct king {
void calculatebmBc(int i)()
{
static if ( i < size -1 )
bmBc[to!string(pattern[i])]=to!int(size-i-1);
// bmBc[pattern[i]] ~= i-1;
calculatebmBc!(i+1)();
}
void calculatebmBc(int i: size-1)() {
}
}
void main(){
king myKing;
const int start = 0;
myKing.calculatebmBc!(start)();
//1. enum bmBcTable = bmBc;
}
The variables bmBc and bmh can't be read at compile time because you define them as regular runtime variables.
You need to define them as enums, or possibly immutable, to read them at compile time, but that also means that you cannot modify them after initialization. You need to refactor your code to return values instead of using out parameters.
Alternatively, you can initialize them at runtime inside of a module constructor.
I want to implement Maybe from Haskell in D, just for the hell of it.
This is what I've got so far, but it's not that great. Any ideas how to improve it?
class Maybe(a = int){ } //problem 1: works only with ints
class Just(alias a) : Maybe!(typeof(a)){ }
class Nothing : Maybe!(){ }
Maybe!int doSomething(in int k){
if(k < 10)
return new Just!3; //problem 2: can't say 'Just!k'
else
return new Nothing;
}
Haskell Maybe definition:
data Maybe a = Nothing | Just a
what if you use this
class Maybe(T){ }
class Just(T) : Maybe!(T){
T t;
this(T t){
this.t = t;
}
}
class Nothing : Maybe!(){ }
Maybe!int doSomething(in int k){
if(k < 10)
return new Just!int(3);
else
return new Nothing;
}
personally I'd use tagged union and structs though (and enforce it's a Just when getting the value)
Look at std.typecons.Nullable. It's not exactly the same as Maybe in Haskell, but it's a type which optionally holds a value of whatever type it's instantiated with. So, effectively, it's like Haskell's Maybe, though syntactically, it's a bit different. The source is here if you want to look at it.
I haven't used the Maybe library, but something like this seems to fit the bill:
import std.stdio;
struct Maybe(T)
{
private {
bool isNothing = true;
T value;
}
void opAssign(T val)
{
isNothing = false;
value = val;
}
void opAssign(Maybe!T val)
{
isNothing = val.isNothing;
value = val.value;
}
T get() #property
{
if (!isNothing)
return value;
else
throw new Exception("This is nothing!");
}
bool hasValue() #property
{
return !isNothing;
}
}
Maybe!int doSomething(in int k)
{
Maybe!int ret;
if (k < 10)
ret = 3;
return ret;
}
void main()
{
auto retVal = doSomething(5);
assert(retVal.hasValue);
writeln(retVal.get);
retVal = doSomething(15);
assert(!retVal.hasValue);
writeln(retVal.hasValue);
}
With some creative operator overloading, the Maybe struct could behave quite naturally. Additionally, I've templated the Maybe struct, so it can be used with any type.
I have a std::vector of this struct:
struct MS
{
double aT;
double bT;
double cT;
};
which I want to use std::sort on as well as std::lower_bound/equal_range etc...
I need to be able to sort it and look it up on either of the first two elements of the struct. So at the moment I have this:
class MSaTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.aT, rhs.aT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.aT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.aT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
class MSbTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.bT, rhs.bT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.bT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.bT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
This allows me to call both std::sort and std::lower_bound with MSaTLess() to sort/lookup based on the aT element and with MSbTLess() to sort/lookup based on the bT element.
I'd like to get away from the functors and use C++0x lambdas instead. For sort that is relatively straightforward as the lambda will take two objects of type MS as arguments.
What about for the lower_bound and other binary search lookup algorithms though? They need to be able to call a comparator with (MS, double) arguments and also the reverse, (double, MS), right? How can I best provide these with a lambda in a call to lower_bound? I know I could create an MS dummy object with the required key value being searched for and then use the same lambda as with std::sort but is there a way to do it without using dummy objects?
It's a little awkward, but if you check the definitions of lower_bound and upper_bound from the standard, you'll see that the definition of lower_bound puts the dereferenced iterator as the first parameter of the comparison (and the value second), whereas upper_bound puts the dereferenced iterator second (and the value first).
So, I haven't tested this but I think you'd want:
std::lower_bound(vec.begin(), vec.end(), 3.142, [](const MS &lhs, double rhs) {
return lhs.aT < rhs;
});
and
std::upper_bound(vec.begin(), vec.end(), 3.142, [](double lhs, const MS &rhs) {
return lhs < rhs.aT;
});
This is pretty nasty, and without looking up a few more things I'm not sure you're actually entitled to assume that the implementation uses the comparator only in the way it's described in the text - that's a definition of the result, not the means to get there. It also doesn't help with binary_search or equal_range.
It's not explicitly stated in 25.3.3.1 that the iterator's value type must be convertible to T, but it's sort of implied by the fact that the requirement for the algorithm is that T (in this case, double) must be LessThanComparable, not that T must be comparable to the value type of the iterator in any particular order.
So I think it's better just to always use a lambda (or functor) that compares two MS structs, and instead of passing a double as a value, pass a dummy MS with the correct field set to the value you're looking for:
std::upper_bound(vec.begin(), vec.end(), MS(3.142,0,0), [](const MS &lhs, const MS &rhs) {
return lhs.aT < rhs.aT;
});
If you don't want to give MS a constructor (because you want it to be POD), then you can write a function to create your MS object:
MS findA(double d) {
MS result = {d, 0, 0};
return result;
}
MS findB(double d) {
MS result = {0, d, 0};
return result;
}
Really, now that there are lambdas, for this job we want a version of binary search that takes a unary "comparator":
double d = something();
unary_upper_bound(vec.begin(), vec.end(), [d](const MS &rhs) {
return d < rhs.aT;
});
C++0x doesn't provide it, though.
The algorithms std::sort, std::lower_bound, and std::binary_search take a predicate that compares two elements of the container. Any lambda that compares two MS objects and returns true when they are in order should work for all three algorithms.
Not directly relevant to what you're saying about lambdas, but this might be an idea for using the binary search functions:
#include <iostream>
#include <algorithm>
#include <vector>
struct MS
{
double aT;
double bT;
double cT;
MS(double a, double b, double c) : aT(a), bT(b), cT(c) {}
};
// template parameter is a data member of MS, of type double
template <double MS::*F>
struct Find {
double d;
Find(double d) : d(d) {}
};
template <double MS::*F>
bool operator<(const Find<F> &lhs, const Find<F> &rhs) {
return lhs.d < rhs.d;
}
template <double MS::*F>
bool operator<(const Find<F> &lhs, const MS &rhs) {
return lhs.d < rhs.*F;
}
template <double MS::*F>
bool operator<(const MS &lhs, const Find<F> &rhs) {
return lhs.*F < rhs.d;
}
int main() {
std::cout << (Find<&MS::bT>(1) < Find<&MS::bT>(2)) << "\n";
std::cout << (Find<&MS::bT>(1) < MS(1,0,0)) << "\n";
std::cout << (MS(1,0,0) < Find<&MS::bT>(1)) << "\n";
std::vector<MS> vec;
vec.push_back(MS(1,0,0));
vec.push_back(MS(0,1,0));
std::lower_bound(vec.begin(), vec.end(), Find<&MS::bT>(0.5));
std::upper_bound(vec.begin(), vec.end(), Find<&MS::bT>(0.5));
}
Basically, by using Find as the value, we don't have to supply a comparator, because Find compares to MS using the field that we specify. This is the same kind of thing as the answer you saw over here: how to sort STL vector, but using the value rather than the comparator as in that case. Not sure if it'd be all that great to use, but it might be, since it specifies the value to search for and the field to search in a single short expression.
I had the same problem for std::equal_range and came up with an alternative solution.
I have a collection of pointers to objects sorted on a type field. I need to find the find the range of objects for a given type.
const auto range = std::equal_range (next, blocks.end(), nullptr,
[type] (Object* o1, Object* o2)
{
return (o1 ? o1->Type() : type) < (o2 ? o2->Type() : type);
});
Although it is less efficient than a dedicated predicate as it introduces an unnecessary nullptr test for each object in my collection, it does provide an interesting alternative.
As an aside, when I do use a class as in your example, I tend to do the following. As well as being shorter, this allows me to add additional types with only 1 function per type rather then 4 operators per type.
class MSbTLess
{
private:
static inline const double& value (const MS& val)
{
return val.bT;
}
static inline const double& value (const double& val)
{
return val;
}
public:
template <typename T1, typename T2>
bool operator() (const T1& lhs, const T2& rhs) const
{
return value (t1) < value (t2);
}
};
In the definition of lower_bound and other STL Algorithms the Compare function is such that the first type must match that of the Forward Iterator and the second type must match that of T (i.e., of the value).
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value, Compare comp );
So one indeed can compare things from different objects (doing what the other response called an Unary Comparator). In C++11 :
vector<MS> v = SomeSortedVectorofMSByFieldaT();
double a_key;
auto it = std::lower_bound(v.begin(),
v.end(),
a_key,
[]{const MS& m, const double& a) {
m.aT < a;
});
And this can be used with other STL algorithm functions as well.
I have the following code in specman:
var x := some.very.long.path.to.a.variable.in.another.struct;
while (x == some_value) {
//do something that uses x;
//wait for something
//get a new value for x
x = some.very.long.path.to.a.variable.in.another.struct;
};
Now, it seems wasteful to write the assignment to x twice; once during initialization and once during the loop.
What I really want to use is a reference to the long variable name, so that I could do:
var x := reference to some.very.long.path.to.a.variable.in.another.struct;
while (x == some_value) {
//do something that uses x;
//wait for something
//no need to update x now since it's a reference
};
Can this be done in specman?
specman/e generally uses references for structs and lists, so if your variable type is either of it your second example should work. For integer or boolean I don't know a way to use a reference for a variable. Anyway, two ideas which might help you:
Add a pointer to the other struct and bind it in a config file:
struct a { other_variable : uint; };
struct b {
other_struct : a;
some_func() is {
var x : uint = other_struct.other_variable;
while (x == some_value) {
x = other_struct.other_variable;
};
};
};
extend cfg {
struct_a : a;
struct_b : b;
keep struct_b.other_struct == struct_a;
};
UPDATE: You can find some more information on this technique in this Team Specman Post.
Wrap your while loop in a function, there you can pass parameters by reference (see help pass reference):
some_func(x : *uint) is {
while (x == some_value) {
// stuff ...
};
};
Hope this helps!
Daniel