I got a wrapper class that has a simple and light-weighted implicit conversion operator to double.
I like to use it as I would use a double, for example:
if (!std::isfinite(myVar)) ...
But visual c++ implementation of std::isfinite(double) is actually a template that get his argument by copy.
So my wrapper class copy constructor is called, and it is not light-weighted.
To avoid this, I have to write:
if (!std::isfinite((double)myVar)) ...
for every call :(
If visual c++ std::isfinite() was defined as is it on cppreference.com, I would not have to cast every call: ([edit] I may be wrong, Integral isn't an actual type... but... [edit] It still should not accept user defined types ?)
bool isfinite( float arg );
bool isfinite( double arg );
bool isfinite( long double arg );
bool isfinite( Integral arg );
I am not sure what the standard says about this.
Is vc++ template std::isfinite standard-conforming ?
Should I report this as a bug on Microsoft connect ?
Should I define my own isfinite(double) that calls std::isfinite ?
edit
Or maybe it is a non-issue as in a release build the calls get inlined and no copy occurs ? (well I'll try to check it right now and update in a few minutes)
edit 2
It doesn't seem to get inlined in a release build with /Ob2 (inline any suitable function)
edit 3
as requested, a sample:
struct DoubleWrapper {
double value;
DoubleWrapper(double value) : value(value) {
printf("copy Ctor\n");
}
DoubleWrapper(const DoubleWrapper & that) : value(that.value) {}
operator double() const {
return this->value;
}
};
int main() {
DoubleWrapper a(rand()); //rand to prevent optimization
auto res = std::isfinite(a);
printf("%d", res); //printf to prevent optimization
}
edit 4
So, based on Ben Voigt comment, this is what I added to my class header:
#include <cmath>
namespace std {
inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
}
Is this a correct solution ?
The only thing is, should I do the same for all <cmath> functions that takes a double ?
edit 5
I'm responding to Shafik Yaghmour answer here, because a comment is too limited (maybe I should start a new question)
If I understand correctly, instead of my edit 4, I should add this to my class header:
inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
using std::isfinite;
Is it required to put it in a namespace, or can I leave it in the "global" namespace ?
But this mean I have to change all my calls from std::isfinite(dw) to isfinite(dw).
Ok, but I realize there are many things I don't understand.
I am confused.
I understand that adding an overload to std is not allowed.
However, adding a template specialization is allowed ? Why ? What difference does it makes ?
Anyway, I tried it, and it is not a solution to my problem because this specialization:
template<> inline __nothrow bool std::isfinite(const MagicTarget<double> & mt) {
return std::isfinite((double)mt);
}
will not be selected by the compiler over the standard one:
template<class _Ty> inline __nothrow bool isfinite(_Ty _X)
{
return (fpclassify(_X) <= 0);
}
To be selected, it should be
template<> inline __nothrow bool std::isfinite(MagicTarget<double> mt) {
return std::isfinite((double)mt);
}
But this would still call the copy Ctor :(
Surprisingly the overload (see edit 4) is selected over the standard template...
I am beginning to think that some C++ rules are too subtle for me :(
But, to begin with, why on earth are cmath functions and especially std::isfinite a template ?
What's the point of accepting anything else that floating points types ?
Anyway, vc++ std::isfinite calls std::fpclassify that is only defined for float, double and long double.
So... What's the point?
I am thinking the standard committee screwed up by allowing cmath functions to be templates. They should only be defined for the types that are relevant, or maybe takes their arguments as universal references.
That's it, sorry for the rant...
I will go for the (not in std) overload.
Thank you!
Addressing edit 4 to your question since through the comments you have come close to a final solution.
You should not be adding it to the std namespace, you should add it to one of your own namespace and rely on argument dependent lookup see Is it a good practice to overload math functions in namespace std in c++ for more details.
Given the standard committee's apparent desire to restrict cmath functions to be called with arithmetic types only, relying on an implicit conversion is not a good idea. So performing an explicit conversion via a cast is the safe way to go for all cmath functions:
isfinite((double)dw)
You can find the details of this in Is it valid to pass non-arithmetic types as arguments to cmath functions?.
Related
I have some utility code that I've been using for years to safely call the ctype family of functions, it looks like this:
template<int (&F)(int)>
int safe_ctype(unsigned char c) {
return F(c);
}
And is used like this:
int r = safe_ctype<std::isspace>(ch);
The idea being that it handles the need to cast the input int to an unsigned value for you in order to prevent undefined behavior. The specifics of this function is somewhat irrelivant though. Here's my question:
Now that in C++17 and later, noexcept is part of the type system, this is a compile error! Because all of the ctype functions are now noexcept.
EDIT: The above sentence is incorrect. the ctype family of functions are not noexcept. I was however getting a compiler error in gcc < 11.2. https://godbolt.org/z/cTq94q5xE
The code works as expected (despite being technically not allowed due to these functions not being addressable) with the latest versions of all 3 major compilers.
I can of course change my function to look like this:
template<int (&F)(int) noexcept>
int safe_ctype(unsigned char c) noexcept {
return F(c);
}
But now it doesn't work when compiled as C++11 or C++14. So I end up having to do something like this:
#if __cplusplus >= 201703L
template<int (&F)(int) noexcept>
int safe_ctype(unsigned char c) noexcept {
return F(c);
}
#else
template<int (&F)(int)>
int safe_ctype(unsigned char c) {
return F(c);
}
#endif
Which is getting increasingly complex for such a simple task. So is there a way to make the function pointer:
valid for C++11 - C++20
Accept both noexcept and non-noexcept when in C++17+
?
I tried doing something like this:
template<class F>
int safe_ctype(unsigned char c) noexcept {
return F(c);
}
In the hopes that it would accept "anything", but sadly, no go.
Thoughts?
Now that in C++17 and later, noexcept is part of the type system, this is a compile error! Because all of the ctype functions are now noexcept.
It is not a compile error. Pointers to noexcept functions are implicitly convertible to pointers to potentially throwing functions, and thus the template accepting a pointer to potentially throwing functions works with both potentially throwing and noexcept functions. Only caveat is that the noexceptedness information is lost and might not be used for optimisation purposes.
Hence, the original solution satisfies both points 1. and 2.
Another problem pointed out in the comments is that the standard library functions (std::isspace) that you intend to use are not designated "addressable". Hence the behaviour of the program is unspecified (possibly ill-formed) due to forming a pointer to them.
To wrap such callable, you could use a lambda instead of a function pointer. But that makes the template itself obsolete since you can change the argument type of the lambda directly:
auto safe_isspace = [](unsigned char c){ return std::isspace(c); };
int r = safe_isspace(ch);
Though we no longer need to pass this into a template, so the same can be achieved with a plain function:
int // or bool?
safe_isspace(unsigned char c) noexcept // ...
Since this involves a bit of identical boilerplate for multiple functions, this is a good candidate for meta-programming.
Because all of the ctype functions are now noexcept.
This is untrue. C++17 did not add noexcept to any C-library functions accessed through the C++ c* headers. You can see here that all of the C++ function declarations do not contain noexcept. And a standard library implementation is not allowed to make non-noexcept functions noexcept.
Secondly, even if it were noexcept, a noexcept function pointer can be converted into a throwing function pointer (but not the other way around). So your code compiles.
But most importantly, C++20 makes it clear that you are not allowed to get function pointers for any C++ standard library function unless it is specifically stated to be "addressable". And there are very few addressable functions in the C++ standard library.
So in C++20, your code will yield UB. You're just going to have to write wrappers for the cctype functions if you want your code to work across all language versions.
I have code that clips some value to be between a range centered around 0 like below.
Eigen::VectorXd a;
Eigen::VecotrXd b;
a = a.cwiseMin(b).cwiseMax(-b); // no temporary created here?
I want to factor out the logic into a function.
One solution:
Eigen::VectorXd Clip(const Eigen::VectorXd& a, const Eigen::VectorXd& b);
a = Clip(a, b);
But I assume this is inefficient as it creates an extra temporary?
Another solution:
void Clip(Eigen::Ref<Eigen::VectorXd> a, const Eigen::VectorXd& b) {
a = a.cwiseMin(b).cwiseMax(-b);
}
But this seems inconvenient to use sometimes:
void SomeFunctionSignatureICannotChange(const Eigen::VectorXd& a, const Eigen::VectorXd& b) {
// Eigen::VectorXd a_clipped = Clip(a, b); would be cleaner.
Eigen::VectorXd a_clipped;
Clip(a_clipped, b);
}
The best solution I can think of:
template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
const Eigen::ArrayBase<DerivedB>& bound)
-> decltype(v.min(bound).max(-bound)) {
return v.min(bound).max(-bound);
}
(I assume 'auto' in this case is fine and not the one that common pitfalls warned against?)
However, the code seems template-heavy and a bit-complicated. For example, trailing return type is discouraged by google style guide here:
Use the new trailing-return-type form only in cases where it's
required (such as lambdas) or where, by putting the type after the
function's parameter list, it allows you to write the type in a much
more readable way. The latter case should be rare; it's mostly an
issue in fairly complicated template code, which is discouraged in
most cases.
Alternatively, if I remove the trailing return type, function return type deduction will kick in. But google style guide seems to also discourage function return type deduction in public headers here
Furthermore, use it only if the function or lambda has a very narrow
scope, because functions with deduced return types don't define
abstraction boundaries: the implementation is the interface. In
particular, public functions in header files should almost never have
deduced return types.
I'm new to Eigen and C++ so not sure if I missed anything. Hope to learn from everyone's comments and suggestions. Thanks!
I confirm that a = a.cwiseMin(b).cwiseMax(-b); does not create any temporary. In your case, using auto return type is highly recommended, and I would also argue that your use case is a perfectly legit exception to the aforementioned rules:
Writing the return type explicitly would be a nightmare and error prone.
This is a very short function that is expected to be inlined. It is thus expected to be declared and defined at the same time. Therefore the second rule does not not really apply.
In c++14 you can even omit the redundancy:
template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
const Eigen::ArrayBase<DerivedB>& bound)
{
return v.min(bound).max(-bound);
}
Consider:
template<typename T>
struct Prop
{
T value;
operator T() { return value; }
};
int main()
{
Prop<float> p1 { 5 };
Prop<std::vector<float>> p2 { { 1, 2, 3 } };
float f1 = p1; // Works fine
float f2_1_1 = p2.value[0]; // Works fine
float f2_1_2 = p2[0]; // Doesn't compile
return 0;
}
Why doesn't the line marked as such compile? Shouldn't it perform implicit conversion using the supplied conversion operator into std::vector<>, so that the [] can be found?
There are (many) other questions on this site that ask variations on this question, but I couldn't find one that I think applies here. Does it have to do with std::vector being a template?
Implicit conversions are not considered for objects of member function calls, including the subscript operator overload.
Consider the consequences if that were allowed: Every single time any undeclared member function is called like this, the compiler would have to figure out all the types that the object can be converted to (note that any other otherwise unrelated type could have a converting constructor), and check if that has declared the missing member function. Not to mention how confusing that would be for the reader of the code (the conversion might be obvious in your conversion operator case, but not in the converting constructor case, and as far as I know, they are not otherwise treated differently).
So is there a notationally convenient way to get Prop to behave the way I want
You would have to define a member function for each of the member function of vector that you want to pass pass through transparently. Here is the subscript operator as an example:
auto operator[](std::size_t pos) {
return value[pos];
}
auto operator[](std::size_t pos) const {
return value[pos];
}
The problem is of course that all wrapped member functions must be explicitly declared. Another problem is arguments whose type depend on T. For example, vector::operator[] uses vector::size_type, which might not be defined for all T that you might use (certainly not for float). Here we make a compromise and use std::size_t.
A less laborious way of creating such "transparent" wrapper is inheritance. A publicly inheriting template would automatically have all the member functions of the parent and be implicitly convertible to it and can be referred by pointers and references of parent type. However, the transparency of such approach is a bit problematic mainly because ~vector is not virtual.
Private inheritance allows same wrapping as your member approach, but with much nicer syntax:
template<typename T>
struct Prop : private T
{
using T::operator[];
using T::T;
};
Note that inheritance approach prevents you from using fundamental types as T. Also, it makes the implicit conversion impossible (even with conversion operator) , so you cannot use Prop as T in free functions that expect T.
PS. Note that your conversion operator returns a value, so the vector must be copied, which may be undesirable. Consider providing reference versions instead:
operator T&&()&& { return *this; }
operator T&()& { return *this; }
operator const T&() const& { return *this; }
the same way that any of the
p2.size();
p2.begin();
p2.push_back(24);
// etc.
don't make sense to compile
also
p2[0];
which is equivalent with
p2.operator[](0);
doesn't make sense to compile\
If you want this behavior (i.e. for Prop<T> to borrow T members) there is a C++ proposal by Bjarne to add the dot operator to the language. I would work the same way that operator -> works for smart pointers. AFAIR it had a lot of controversy and so I wouldn't hold my breath for it.
A bit of background for the operator dot proposal—Bjarne Stroustrup
Operator Dot (R3) - Bjarne Stroustrup, Gabriel Dos Rei
Smart References through Delegation: An Alternative to N4477's Operator Dot - Hubert Tong, Faisal Vali
Alternatives to operator dot - Bjarne Stroustrup
I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.
So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?
I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".
In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.
So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.
However, this doesn't actually work, at least not using GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
This results in :
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?
"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.
If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.
I've been playing with C++ recently, and I just stumbled upon an interesting precedence issue. I have one class with two operators: "cast to double" and "+". Like so:
class Weight {
double value_;
public:
explicit Weight(double value) : value_(value) {}
operator double() const { return value_; }
Weight operator+(const Weight& other) { return Weight(value_ + other.value_); }
};
When I try to add two instances of this class...
class Weighted {
Weight weight_;
public:
Weighted(const Weight& weight) : weight_(weight) {}
virtual Weighted twice() const {
Weight w = weight_ + weight_;
return Weighted(w);
}
};
...something unexpected happens: the compiler sees the "+" sign and casts the two weight_s to double. It then spits out a compilation error, because it can't implicitly cast the resulting double back to a Weight object, due to my explicit one-argument constructor.
The question: how can I tell the compiler to use my own Weight::operator+ to add the two objects, and to ignore the cast operator for this expression? Preferably without calling weight_.operator+(weight_), which defeats the purpose.
Update: Many thanks to chris for pointing out that the compiler is right not to use my class's operator+ because that operator is not const and the objects that are being +ed are const.
I now know of three ways to fix the above in VS2012. Do see the accepted answer from chris for additional information.
Add the explicit qualifier to Weight::operator double(). This
doesn't work in VS 2012 (no support), but it stands to reason that
it's a good solution for compilers that do accept this approach (from the accepted answer).
Remove the virtual qualifier from method Weighted::twice, but don't ask me why this works in VS.
Add the const qualifier to method Weight::operator+ (from the accepted answer).
Current version:
First of all, the virtual should have nothing to do with it. I'll bet that's a problem with MSVC, especially considering there's no difference on Clang. Anyway, your twice function is marked const. This means that members will be const Weight instead of Weight. This is a problem for operator+ because it only accepts a non-const this. Therefore, the only way the compiler can go is to convert them to double and add those.
Another problem is that adding explicit causes it to compile. In fact, this should remove the compiler's last resort of converting to double. This is indeed what happens on Clang:
error: invalid operands to binary expression ('const Weight' and 'const Weight')
Weight w = weight_ + weight_;
note: candidate function not viable: 'this' argument has type 'const Weight', but method is not marked const
Finally, making operator+ const (or a free function) is the correct solution. When you do this, you might think you'll add back this route and thus have another error from ambiguity between this and the double route, but Weight to const Weight & is a standard conversion, whereas Weight to double is a user-defined conversion, so the standard one is used and everything works.
As of the updated code in the question, this is fine. The reason it won't compile is the fault of MSVC. For reference, it does compile on Clang. It also compiles on MSVC12 and the 2013 CTP.
You may be storing the result in a Foo, but there is still an implicit conversion from double to Foo needed. You should return Foo(value_ + other.value_) in your addition operator so that the conversion is explicit. I recommend making the operator a free function as well because free operators are (almost) always at least as good as members. While I'm at it, a constructor initializer list would be a welcome change, too.
In addition, from C++11 onward, a generally preferred choice is to make your conversion operator explicit:
explicit operator double() const {return value_;}
Also note the const added in because no state is being changed.