I writing a DSL in IronPython. Overloading operators in C# and using
them in python works fine, until you get to the assignation (=) operator.
Using the implicit cast overload solves the problem on the C# side, but it does not work in python.
This is the minimum example that reproduces the error:
class FloatValue
{
public FloatValue(float value)
{
this.value = value;
}
public static implicit operator FloatValue(float value)
{
return new FloatValue(value);
}
public float value;
}
Then I execute:
FloatValue value = 5.0f // It works!!!
But in Python:
# value is already an instance of FloatValue, it comes from somewhere. It's considered
# an immutable value, so there is no problem with generating a new instance.
value = 5.0 # Assigns the value, but does not work :(
I get the following exception:
Expected FloatValue, got float
How can I make it work?
Python does not support single-precision floating point values. The literal 5.0 is therefore (in case of IronPython) represented as a System.Double.
You can either change your DSL to use double-precision or just implicitly convert down to float by adding
public static implicit operator FloatValue(double value)
{
return new FloatValue(Convert.ToSingle(value));
}
Related
In Python itself, you'd write simply float(f) where f is a Python Decimal. That yields a double type (called a float in Python).
But I need to do this in boost::python. My code (abridged) is
double toDouble(boost::python::object obj)
{
std::string type = boost::python::extract<std::string>(obj.attr("__class__").attr("__name__"));
std::string module = boost::python::extract<std::string>(obj.attr("__class__").attr("__module__"));
std::string cls = module + "." + type;
if (cls == "decimal.Decimal"){
double f = boost::python::extract<double>(obj);
return f;
}
throw "Oops";
}
But I get an error
No registered converter was able to produce a C++ rvalue of type
double from this Python object of type decimal.Decimal
How do I do this? I can't imagine it's complicated. Clearly I'm missing something.
The code you need in the if block is
static boost::python::object builtins
= boost::python::import("builtins");
static boost::python::object function
= boost::python::extract<boost::python::object>(builtins.attr("float"));
boost::python::object ret = function(obj);
double f = boost::python::extract<double>(ret);
I am indeed essentially using the Python function float(obj).
And by the looks of things, you are already familiar with boost::python::extract.
float is a built-in python function. See https://docs.python.org/3/library/functions.html. So the first statement is the importing of the module containing the built-in functions. The second statement obtains the float function.
The third one calls it, on the lines of the Boost documentation "Calling Python Functions And Methods".
You might be able to pull this together to register this extraction, which probably, knowing the beautiful way in which Boost is designed, amounts to little more than specialising a template.
I am writing an eosio smart contract, which is basically C++ compiled to Webassembly.
When using stof or strtof (string to float), I get the error cause: access violation\n${callstack}when running the action (basically a function). Interestingly, stoi works fine.
Example code
//Will both give the error for any string
//including both valid float representations (e.g. "10.23")
//and also invalid float representations (e.g. "Hello World")
ACTION testcontract::parser1(string text) {
float val = stof(text);
}
ACTION testcontract::floatparser2(string text) {
float val = strtof(text.c_str(), nullptr);
}
//Will work
ACTION testcontract::intparser(string text) {
uint32_t val = stoi(text);
}
Is this because of some design restrictions of Webassembly? Should this work in Webassembly in general (without the eosio smart contract on top of it). Or am I just doing something wrong here?
Is there any way to invoke a user defined literal on lvalues?
e.g I would like to
int operator "" _xor1(int a) { return a^1; }
// Works fine
17_xor1;
auto myint = get_something_only_availabe_at_runtime();
// Any way to use _xor1 on myint?
_xor1(myint); // Doesn't work
Also, when compiling the following code at the compiler explorer, I was surprised to discover that it was all resolved at runtime, although all data is available at compile time. Why is that?
constexpr int operator "" _xor1(unsigned long long a) {
return a^1;
}
int main() {
// This code resolves the user defined literal at runtime on gcc,
// msvc and clang - I don't see why I can't use the
// user defined literal at runtime?
return 17_xor1;
}
I'm not sure you really want to - as commented, you're probably better off defining a normal function and calling that - but you can call it using:
operator""_xor1(myInt);
See User-defined literals for more information.
No, you cannot invoke a user-defined literal on a variable populated at runtime. Nor do you need to. Just define a standalone function that different pieces of code can invoke when needed, eg:
template <typename T>
T do_xor1(T a) { return a^1; }
int operator "" _xor1(unsigned long long a) { return do_xor1(a); }
// Works fine
17_xor1;
auto myint = get_something_only_availabe_at_runtime();
do_xor1(myint);
I am assigning to a std::function<double()> a lambda expression. This snippet works
if(fn_type==exponential)
k.*variable = [=,&k](){ return initial*exp(-k.kstep*par); };
else
k.*variable = [=,&k](){ return initial*pow(k.kstep, par); };
whereas if I want to use the ternary operator
k.*variable = (fn_type==exponential ? [=,&k](){ return initial*exp(-k.kstep*par); } : [=,&k](){ return initial*pow(k.kstep, par); });
I get the following error:
error: no match for ternary ‘operator?:’ in <awfully long template error, because this whole thing is in a class defined in a function...>
Is this a gcc bug (I'm using 4.7.2)? Otherwise why is there this limit in the standard?
The second and third operands of the conditional operator must have the same type or there must be some common type to which they can both be converted that the compiler can figure out. There are only a handful of conversions that the compiler will consider.
Your two lambda expressions have different types, and there is no common type to which they can both be converted (conversions to user-defined types, like std::function<double()>, cannot be considered because there are potentially an infinite number of valid target types).
You can directly convert each of the operands to std::function<double()>:
k.*variable = fn_type==exponential
? std::function<double()>([=,&k](){ return initial*exp(-k.kstep*par); })
: std::function<double()>([=,&k](){ return initial*pow(k.kstep, par); });
But really, it's cleaner with the if/else.
Also faced this issue - won't compile!
'if/else' not good for me, I would like auto type deducing feature turn on.
auto memcpy_traits =
[&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
std::memcpy(line_dst, curr_src, bytes_to_copy);
line_dst += bytes_to_copy;
curr_src += bytes_to_copy;
}
:
[&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
std::memcpy(line_dst, curr_src, bytes_to_copy);
line_dst += bytes_to_copy;
curr_src += bytes_to_copy;
};
I've recently been doing a huge refactoring where I was changing a lot of my code to return booleans instead of an explicit return code. To aid this refactoring I decided to lean on the compiler where possible by getting it to tell me the places where my code needed to be changed. I did this by introducing the following class (see here for the lowdown on how this works):
///
/// Typesafe boolean class
///
class TypesafeBool
{
private:
bool m_bValue;
struct Bool_ {
int m_nValue;
};
typedef int Bool_::* bool_;
inline bool_ True() const { return &Bool_::m_nValue; }
inline bool_ False() const { return 0; }
public:
TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
operator bool_() const { return m_bValue ? True() : False(); }
};
Now, instead of using a normal bool type as the return type, I used this class which meant that I couldn't compile something like this any more:
TypesafeBool SomeFunction();
long result = SomeFunction(); // error
Great: it has made the refactoring manageable on a huge codebase by letting the compiler do a lot of the hard work for me. So now I've finished my refactoring and I'd quite like to keep this class hanging around and carry on using it since it affords us an extra level of safety that the built-in bool type doesn't.
There is however one "problem" which is preventing me from doing this. At the moment we make heavy use of the ternary operator in our code, and the problem is that it is not compatible with this new class without explicit casts:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : false ); // error: different types used
TypesafeBool result = ( 1 == 2 ? SomeFunction() : (TypesafeBool)false );
If I could "solve" this issue so that I could use my class in a seamless manner I would probably carry on using it throughout the codebase. Does anyone know of a solution to this issue? Or is it just impossible to do what I want?
In the context of the conditional operator, the type of the expression is the common type of the last two operands. The complete rules to determine this common type are a bit complex, but your case happens to be trivial: if one of the two possible return values is a class type, the other value must have the same class and the common type is obviously also that class.
That means that if one of the operands is a TypesafeBool, then the other must be as well.
Now the problem you're really trying to solve has been solved before. The trick is not providing a class; instead use a typedef. See for instance safe bool.
class CCastableToBool
{
public:
// ...
operator bool() const
{
//...
{
return true;
}
//...
return false;
}
private:
// ...
};
but beware, in C++ it is considered really dangerous to have a class that can be casted to bool. You are warned :-)
you can read this there, SafeBool
You should explicitely call TypesafeBool::True() in all your ternary tests.
TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );
I don't know about a seamless manner, the ternary operator has some restrictions on its use...
However, why don't you define two constants ?
TypesafeBool const True = TypesafeBool(true);
TypesafeBool const False = TypesafeBool(false);
And then:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : False );
Of course, it's a bit unorthodox since I play on the capitalization to avoid reusing a reserved word :)
Is it a possibility to make the constructor of TypesafeBool explicit? Of course, now the usage has to be
TypesafeBool result( 1 == 2 ? b : false );
Could you use an assignment operator that takes in a bool as the external argument, as well as one that takes a TypesafeBool? It might be something to try out...
Nice try, but if your code base is large, you are probably better off using a static checker such as PC-Lint to look for implicit bool<->int conversions instead.