How I can prevent the last line of this code from compiling?
#include <boost/optional.hpp>
int main()
{
typedef boost::optional<int> int_opt;
int_opt opt = 0;
bool x = opt; // <- I do not want this to compile
}
The last line doesn't examine opt's contained int value, but instead compiles as a type conversion to bool, and doesn't seem to be what the user intended.
The safe bool idiom seems to be relevant here?
The whole point of boost::optional is to enable code like this:
void func(boost::optional<int> optionalArg)
{
if (optionalArg) {
doSomething(*optionalArg);
}
}
So the implicit conversion to bool is a feature, and should not be prevented from compiling.
The problem that you describe used to be the case for the older versions of Boost. Ever since 1.56 release boost::optional has an explicit conversion to bool and the code that you show does not compile anymore (exactly the way you wanted). See here.
If you're using optional then you need to be able to determine if it's set before using it. The way this is implemented is with the (effectively bool) conversion.
It doesn't in my mind follow that the user didn't want what's actually written there: They should know that it's an optional and that they're checking it for validity.
Since the conversion is a built in part of boost::optional I'm not aware of any way to directly remove it.
You could of course implement a wrapper class for your particular int need that provides just the parts of the optional interface that you want, possibly with an explicit function that checks validity.
Alternately you could always use template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; or its non-const version when working with optionals to make it explicit what's happening.
Related
While I was on a short break, my workplace switched to using a static code analyzer.
They ran it over the project I am working on and one particular problem flagged by the analyzer goes like this (simplified example):
struct calcSomething
{
int result;
calcSomething() : result(0) {}
void operator()(const int v) { /*does something*/ }
operator int() const { return result; }
};
void foo()
{
std::vector<int> myvector(10);
// exercise for reader: stick some values in `myvector`
int result = std::for_each(myvector.begin(), myvector.end(), calcSomething());
}
The analyzer flags the following issues:
warning: CodeChecker: 'operator int' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
operator int() const { return result; }
The suggested fix to the functor reads:
struct calcSomething
{
...
explicit operator int() const { return result; }
};
But if I fix my functor as suggested, the static analyzer quickly flags the following issue:
warning: CodeChecker: no viable conversion from '(anonymous namespace)::calcSomething' to 'int' [clang-diagnostic-error]
I now need to add the explicit cast:
void foo()
{
...
int total = static_cast<int>(std::for_each(myvector.begin(), myvector.end(), calcSomething()));
}
The above example is a mere simplification of the real problem which would otherwise just add filler and no substance.
I have seen plenty of examples of functors like the one I describe here in text books and programming reference web pages.
I have never considered these unsafe. I have never seen anyone flag these as unsafe.
So does the code analyzer have a point?
Or is it a little overzealous to make my functor's conversion operator explicit and as a result make me add the static cast?
Purely from an aesthetic point, I feel that a simple problem with an elegant solution now accrues a lot of ugly syntactic padding.
But perhaps that is the price we pay for writing safe(r) code.
side note: TIL that explicit applies not only to ctors
Edit
It seems some people are unable to read beyond the example code I provided (pretty textbook stuff) and still suggest other algorithms/idioms, completely failing to see that the actual question is about conversion operators on functors whose sole purpose is to calculate and return an algorithm's result.
If the question was about how to improve on an adding algorithm, then the title would have said so.
So I decided to hide any implementation details in this edit to make it easier for these people.
Sorry that some of the comments below now no longer make any sense, but the record got stuck so I had to move the needle a bit in order to move things forward (hopefully).
I would do away with any conversion operators altogether. What's wrong with:
int result = std::for_each(...).get();
where get() does the same as your current operator int.
You know that the result of for_each is not an integer, it's your function object. Why, why would you want to avoid making the conversion from a function to a value explicit? It is, by all means, a questionable idea. Sure, you can still do it, but you want clean warning-free code right? Well, clean, warning free code, in my book, should not auto-convert functions to integers. I agree static_cast is almost equally ugly, that's why I am suggesting a named function
Let's take the following function declaration:
void print(SomeType const* i);
Here, the const* nature of the argument i suggest the intent, that the parameter is optional, since it may be nullptr. If this was not intended, the argument would instead just be a const&. Communicating optional-semantics were certainly not the original intent for designing pointers, but using them to do so happens to work just fine for a long time.
Now, since using raw pointers is generally discouraged in modern C++ (and should be avoided in favor of std::unique_ptr and std::shared_ptr to precisely indicate particular ownership-semantics), I wonder how to properly indicate function parameters' optional-semantics without passing by value, i. e. copying, as
void print(std::optional<SomeType> i);
would do.
After thinking about it for a while I came up with the idea of using:
void print(std::optional<SomeType const&> i);
This would in fact be most precise. But it turns out that std::optional cannot have reference types.¹
Also, using
void print(std::optional<SomeType> const& i);
would in no way be optimal, since then we would require our SomeType to exists in an std::optional on the caller-side, again possibly (or rather likely) requiring a copy there.
Question: So what would be a nice modern approach for allowing optional arguments without copying? Is using a raw pointer here still a reasonable approach in modern C++?
¹: Ironically the depicted reason for why std::optional cannot have reference types (controversy about rebinding or forwarding on assignment) does not apply in the case of std::optionals of const references, since they cannot be assigned to.
Accepting a raw pointer is perfectly fine and is still done in plenty of "modern" codebases (which I'll note is a fast-moving target). Just put a comment on the function saying that it's allowed to be null and whether the function holds a copy of the pointer after the call (i.e. what are the lifetime requirements for the pointed-to value).
Does function overloading provide a clean solution here? E.g. To declare both the const ref and empty param list versions of the function?
This may depend on what the function body does in the no argument/null case - and how you can manage the two implementations to minimize code overlap.
Raw pointers are usually fine for this type of optional argument passing, actually one of the only times it is fine to use raw pointers overall. This is also the canonical recommended way.
That being said, boost::optional does allow you to use reference optional and const reference optionals. It was decided against to have this feature in the std library (for reasons I leave out here).
This is actually what std::reference_wrapper was made for. Also see Does it make sense to combine optional with reference_wrapper? for more reasoning as to when to use it, and when not to use it.
Here, the const* nature of the argument i suggest the intent, that the parameter is optional since it may be nullptr.
[...]
So what would be a nice modern approach for allowing optional arguments without copying?
Allowing an optional argument (not in the std::optional sense, but in the semantic sense) with differing implementation variations based on whether the optional argument is present or not sound like an ideal candidate for overloading:
struct SomeType { int value; };
namespace detail {
void my_print_impl(const SomeType& i) {
std::cout << i.value;
}
} // namespace detail
void my_print() {
const SomeType default_i{42};
detail::my_print_impl(default_i);
}
void my_print(const SomeType& i) {
detail::my_print_impl(i);
}
or
namespace detail {
void my_print_impl() {
std::cout << "always print me\n";
}
} // namespace detail
void my_print() {
detail::my_print_impl();
}
void my_print(const SomeType& i) {
detail::my_print_impl();
std::cout << "have some type: " << i.value;
}
or some similar variation, depending on what your implementation should do depending on the existence/non-existence of the optional argument.
Optional references, otherwise, are basically raw pointers, and the latter may just as well be used (if overloading is not applicable).
For convenience, I'd like to be able to cast between two types defined in other libraries. (Specifically, QString from the Qt library and UnicodeString from the ICU library.) Right now, I have created utility functions in a project namespace:
namespace MyProject {
const icu_44::UnicodeString ToUnicodeString(const QString& value);
const QString ToQString(const icu_44::UnicodeString& value);
}
That's all well and good, but I'm wondering if there's a more elegant way. Ideally, I'd like to be able to convert between them using a cast operator. I do, however, want to retain the explicit nature of the conversion. An implicit conversion should not be possible.
Is there a more elegant way to achieve this without modifying the source code of the libraries? Some operator overload syntax, perhaps?
You could always do exactly what you're doing but make it look more like casting. There may even be some reasonable argument for doing so, such as being able to override for more types and retain the same syntax.
Consider:
template < typename DestType, typename SourceType >
DestType string_cast(SourceType const& source)
{
return string_cast_impl<DestType,SourceType>::apply(source);
}
template < typename DestType, typename SourceType >
struct string_cast_impl;
template < >
struct string_cast_impl<QString,icu_44::UnicodeString>
{
QString apply(icu_44::UnicodeString const& val) { return MyProject::ToQString(value); }
};
// etc...
You might consider not using the impl struct (because you don't need to partially specialize...ever), or you might consider enhancing it so that you can use enable_if. At any rate, you'd have a common interface for string type conversion such that you don't need to remember what function to call...just call string_cast<Dest>(source).
Edit: come to think of it, I'm doing what you're doing in one of my projects to convert from std::string to/from std::wstring. I think I'll use this alternative to replace that.
If what you're striving for is to be able to say
QStrign qs;
UnicodeString us(qs);
or
UnicodeString us;
QString qs(us);
then no, you can't do that unless you can change either of the classes. You can, of course, introduce a new string:
NewString ns;
UnicodeString us(ns);
QString qs(us);
NewString nsus(us);
NewString nsqs(qs);
I'm not sure about this approach's elegance though, compared with your two explicit conversion functions.
A possible solution would be to wrap these types and provide explicit conversion constructors. I take it you cannot modify the source of both QString and icu_44::UnicodeString which would be the most natural place for the conversion constructors to reside. The use of the keyword explicit prohibits implicit conversion, hence conversions can only occur when you write QString converted(original) with original a value of typeicu_44::UnicodeString or vice versa.
The only problem with this approach is that you have to wrap your data types. I don't know whether you'll ever need more operations on these types currently not provided in the actual libraries or not, but if that's the case, wrapping is a possible way to go
Side question, do you mean to use the 4.4 namespace directly and not just icu::UnicodeString ?
For convenience, I'd like to be able to cast between two types defined in other libraries. (Specifically, QString from the Qt library and UnicodeString from the ICU library.) Right now, I have created utility functions in a project namespace:
namespace MyProject {
const icu_44::UnicodeString ToUnicodeString(const QString& value);
const QString ToQString(const icu_44::UnicodeString& value);
}
That's all well and good, but I'm wondering if there's a more elegant way. Ideally, I'd like to be able to convert between them using a cast operator. I do, however, want to retain the explicit nature of the conversion. An implicit conversion should not be possible.
Is there a more elegant way to achieve this without modifying the source code of the libraries? Some operator overload syntax, perhaps?
You could always do exactly what you're doing but make it look more like casting. There may even be some reasonable argument for doing so, such as being able to override for more types and retain the same syntax.
Consider:
template < typename DestType, typename SourceType >
DestType string_cast(SourceType const& source)
{
return string_cast_impl<DestType,SourceType>::apply(source);
}
template < typename DestType, typename SourceType >
struct string_cast_impl;
template < >
struct string_cast_impl<QString,icu_44::UnicodeString>
{
QString apply(icu_44::UnicodeString const& val) { return MyProject::ToQString(value); }
};
// etc...
You might consider not using the impl struct (because you don't need to partially specialize...ever), or you might consider enhancing it so that you can use enable_if. At any rate, you'd have a common interface for string type conversion such that you don't need to remember what function to call...just call string_cast<Dest>(source).
Edit: come to think of it, I'm doing what you're doing in one of my projects to convert from std::string to/from std::wstring. I think I'll use this alternative to replace that.
If what you're striving for is to be able to say
QStrign qs;
UnicodeString us(qs);
or
UnicodeString us;
QString qs(us);
then no, you can't do that unless you can change either of the classes. You can, of course, introduce a new string:
NewString ns;
UnicodeString us(ns);
QString qs(us);
NewString nsus(us);
NewString nsqs(qs);
I'm not sure about this approach's elegance though, compared with your two explicit conversion functions.
A possible solution would be to wrap these types and provide explicit conversion constructors. I take it you cannot modify the source of both QString and icu_44::UnicodeString which would be the most natural place for the conversion constructors to reside. The use of the keyword explicit prohibits implicit conversion, hence conversions can only occur when you write QString converted(original) with original a value of typeicu_44::UnicodeString or vice versa.
The only problem with this approach is that you have to wrap your data types. I don't know whether you'll ever need more operations on these types currently not provided in the actual libraries or not, but if that's the case, wrapping is a possible way to go
Side question, do you mean to use the 4.4 namespace directly and not just icu::UnicodeString ?
I've been looking for an example that shows how to implement constraints in C++ (or a boost library that lets me do this easily), but without much luck. The best I could come up with off the top of my head is:
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
template<typename T>
class constrained
{
public:
constrained(boost::function<bool (T)> constraint, T defaultValue, T value = defaultValue)
{
ASSERT(constraint(defaultValue));
ASSERT(constraint(value));
this->value = value;
this->defaultValue = defaultValue;
this->constraint = constraint;
}
void operator=(const T &assignedValue)
{
if(constraint(assignedValue))
value = assignedValue;
}
private:
T value;
T defaultValue;
boost::function<bool (T)> constraint;
};
int main(int argc, char* argv[])
{
constrained<int> foo(boost::lambda::_1 > 0 && boost::lambda::_1 < 100, 5, 10);
foo = 20; // works
foo = -20; // fails
return 0;
}
Of course there's probably some more functionality you'd want from a constraint class. This is just an idea for a starting point.
Anyway, the problem I see is that I have to overload all operators that T defines in order to make it really behave like a T, and there is no way for me to find out what those are. Now, I don't actually need constraints for that many different types, so I could just leave out the template and hard code them. Still, I'm wondering if there's a general (or at least more succint/elegant) solution or if there's anything seriously wrong with my approach.
Looks good as for tiny example. But be sure to implement all the operators and handle somehow wrong values.
foo = 100; // works
++foo; // should throw an exception or perform an assert
Use boost operators to help you with operators overload.
And probably it would be good to have an option as a template parameter: either exception or assertion.
I'd use such class. It is always better to have an index parameter that auto check vector range and do assertion.
void foo( VectorIndex i );
You don't need to overload all operators as others have suggested, though this is the approach that offers maximum control because expressions involving objects of type constrained<T> will remain of this type.
The alternative is to only overload the mutating operators (=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, pre and post ++, pre and post --) and provide a user-defined conversion to T:
template<typename T>
class constrained {
... // As before, plus overloads for all mutating operators
public:
operator T() const {
return value;
}
};
This way, any expression involving a constrained<T> object (e.g. x + y where x is int and y is constrained<int>) will be an rvalue of type T, which is usually more convenient and efficient. No safety is lost, because you don't need to control the value of any expression involving a constrained<T> object -- you only need to check the constraints at a time when a T becomes a constrained<T>, namely in constrained<T>'s constructor and in any of the mutating operators.
Boost.Constrained_Value may be of interest to you. It was reviewed last December, but it is not in the latest Boost release. IIRC, the review was mostly positive, but the decision is still pending.
I agree with Mykola Golubyev that boost operators would help.
You should define all the operators that you require for all the types you are using.
If any of the types you are using don't support the operator (for example the operator++()), then code that calls this method will not compile but all other usages will.
If you want to use different implementations for different types then use template specialisation.
I might just be confused, but if you are facing parameters that must not violate specific constraints, wouldn't it be easiest to create a class for them, checking for constraints in constructors and assignment operators?
Boost actually had such a library under discussion (I don't know what became of it). I've also written my own version of such a type, with slightly different behaviour (less flexible, but simpler). I've blogged an admittedly somewhat biased comparison here: Constrained vs. restricted value types
Edit: apparently Eric knows better what happened to boost's implementation.