Wouldn't it make sense to overload with respect to noexcept? - c++11

I am trying to understand the noexcept feature.
I know it could be confusing, but besides that could noexcept be deduced from the calling function when possible.
This is a non working example of this situation,
void f(){}
void f() noexcept{} // not allowed in c++
void g(){f();} // should call f
void h() noexcept{f();} // should call f noexcept
int main(){
g();
h();
}
If there is no try/catch block in the calling function (h) then the compiler could deduce that one is interested in calling a particular f.
Is this pattern used in some other workaround form?
All I can imagine is somthing like this but it is not very generic:
template<bool NE> void F() noexcept(NE);
template<>
void F<true>() noexcept(true){}
template<>
void F<false>() noexcept(false){}
void g(){F<noexcept(g)>();} // calls F<false>
void h() noexcept{F<noexcept(h)>();} // call F<true>
Some may wonder why that would make sense.
My logic is that that C++ allows to overload with respect to const, both a argument of functions and a member functions.
const member functions prefer to call const member overloads for example.
I think it would make sense for noexcept functions to call noexcept "overloads". Specially if they are not called from a try/catch block.

It makes sense,
Of course it would make sense in principle. One version of the function could run, say, a faster algorithm, but which requires dynamically-allocated extra scratch memory, while the noexcept version could use a slower algorithm with O(1) extra space, on the stack.
but wouldn't be able to resolve the overload ...
As you may know, it's perfectly valid to call noexcept(false) functions from noexcept(true) functions. You're just risking a terminate instead of an exception being thrown; and sometimes - you're not risking anything because you've verified that the inputs you pass cannot trigger an exception. So, how would the compiler know which version of the function you're calling? And the same question for the other direction - maybe you want to call your noexcept(true) function from within a noexcept(false) function? That's also allowed.
... and - it would be mostly syntactic sugar anyway
With C++11, you can write:
#include <stdexcept>
template <bool ne2>
int bar(int x) noexcept(ne2);
template<> int bar<true>(int) noexcept { return 0; }
template<> int bar<false>(int) { throw std::logic_error("error!"); }
and this compiles just fine: GodBolt.
So you can have two function with the same and same arguments, differing only w.r.t. their noexcept value - but with different template arguments.

I don't think overloading on noexcept makes a lot sense on its own. For sure, it makes sense wether your function f is noexcept, especially when called from h, as h needs to catch the possible exception and call std::abort.
However, just overloading on noexcept ain't a good thing to do. It's like disabling exceptions in the standard library. I'm not arguing you shouldn't do that, though, you do loose functionality because of it. For example: std::vector::at throws if the index is invalid. If you disable exceptions, you don't have an alternative for using this functionality.
So if you really want to have 2 versions, you might want to use other alternatives to indicate failure. std::optional, std::expected, std::error_code ...
Even if you manage to overload on noexcept, your function will have a different return type. This ain't something I would expect as a user from your framework.
Hence, I think it's better to overload is a different way, so the user can choose which variant to use, this by using the boolean explicitly, std::nothrow as argument output argument with std::error_code. Or maybe, you should make a choice on the error handling strategy you use in your library and enforce that to your users.

Related

C++ command pattern with large number of params

I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.

Automatically call move constructors

I have the following code sample:
void MyClass::Register2(std::string name, std::string email)
{
m_name = std::move(name);
m_email = std::move(email);
}
void MyClass::Register1(std::string name)
{
Register2(std::move(name), "invalid_email");
}
My questions are:
Do I need to use std::move when calling Register2() from Register1()?
Do I need to call std::move() inside Register1()?
If the answer for question 2. is yes, would be possible to have a dedicated operator instead?
For example:
void MyClass::Register2(std::string name, std::string email)
{
m_name <= name; // perform move
m_email <= email; // perform move
}
Do I need to use std::move when calling Register2() from Register1()?
Yes, because name is an lvalue and you want to turn it into an rvalue.
Do I need to call std::move() inside Register1()?
Yes, for the same reason as above.
If the answer for question 2. is yes, would be possible to have a dedicated operator instead?
It would be possible, but I do not think it has been proposed. Also, if it were to be proposed, I do not think it would be accepted as it doesn't bring much value over std::move.
Yes
Yes
No
std::move looks something like this
template<typename T>
std::remove_reference_t<T>&& move(T&& value) {
return static_cast<std::remove_reference_t<T>&&>(value);
}
All it does is it casts the thing you pass as the argument to an rvalue. This step is essential because arguments, even if you pass an rvalue, are always lvalues (because they have names). Lvalues are not moveable, therefore if you don't cast them to an rvalue, move mechanics won't kick in and they will be simply copied.
Operators are functions and there are no exceptions in this case. Special move operator hasn't been proposed and is extremly unlikely to be because it would make the standard longer and more complex (compilers would also be heavily affected) for a feature that saves a couple chars.

Variadic template aliases or functions?

Supposing one needs to obtain a logical value based on a
pack of template parameters, is there a reason to prefer an alias approach
vs a function approach?
Example:
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>,
bool_pack<true, bs...>>;
as opposed to
template<class none=void>
constexpr bool all_true() { return true; }
template<bool First, bool... Rest>
constexpr bool all_true() {
return First and all_true<Rest...>();
}
Time required for compiling your example implementations
... should be measured, of course. That said, I have seen micro-benchmarks where the std::is_same approach leads to significantly shorter compile times; even compared to the C++17 fold expression (true && ... && bs) with the respective compilers. The recursive "function approach" you gave as an example should be clearly inferior in compile-time performance.
Note, however, that one could surely offer the most convenient interface by providing a wrapper around the most "efficient" (regarding compile-time effort) implementation.
Convenience in using the "interface"
Given these two choices, I would prefer the alias approach. If you need the result of that helper as a type (for inheritance, template-metaprogramming with specializations, or for tag dispatch), the alias yields cleaner syntax compared to, say, std::bool_constant<all_true_v<some_condition(), some_other_condition()>()>. In the other direction, it is simple to obtain a value of type bool from the alias: all_true<some_condition(), some_other_condition()>{} (relying on implicit type conversion).
Since C++14, yet another (fancy?) choice is to provide a value by a constexpr variable template which has either type std::true_type or std::false_type. By implicit conversion to bool it can readily be used where plain true or false is required, but it can also be passed as a function argument without losing its compile-time guarantee.
template<bool... bs>
constexpr auto all_true_c = typename std::is_same<
bool_pack<true, bs...>, bool_pack<bs..., true>
>::type{};
It may be a good strategy to follow the naming conventions used in the <type_traits> header of modern C++ providing both forms. If some utility is supposed to provide a value, one finds helper variable templates such as std::is_same_v:
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;// (since C++17)
if some helper is supposed to provide a type, one finds helper types such as std::decay_t:
template<class T>
using decay_t = typename decay<T>::type;// (since C++14)
... in addition to the conventional utilities without suffix, respectively.

How do I pass static_cast<T> as a function?

I have a type A that's designed to be implicitly casted to type B. Here's an example case I'd like to use it in:
// Current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; }); // Thanks, Kerrek SB.
// Ideal implementation - Won't compile, expected '(' after 'static_cast'.
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
static_cast<B>);
What can I do to make the latter option compile?
static_cast<B>, while it is invoked with function-call syntax cannot be passed like other callable things. E.g., there's no way to use & to get a function pointer to it.
You can use a short little lambda to achieve something similar to passing a function pointer to static_cast<B>, as you do in your current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; });
Another option--in this particular case--would be to construct a vector<B> from the vector<A>:
std::vector<B> vec_of_b(vec_of_a.begin(), vec_of_a.end());
(This answer is a summary of the comments on both the question and bipll's answer.)
Build a functor enclosing static_cast:
template <typename T>
struct StaticCast
{
template <typename U>
T operator()(const U& rhs)
{
return static_cast<T>(rhs);
}
};
With this, you can call std::transform:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b), StaticCast<b>());
It can be used in the case the output vector is already defined in place of the lambda shown in comments. If not, prefer the constructor mentioned in another answer**.
This functor version is compliant with C++98 if needed -- even if OP is tagged C++11, it may be worthy to note this point.
** Note that with this particular constructor, a warning C4244 is raised with VS compiler (tested with VS2017).
Yes, that's the way anonymous functions work in C++, and static_cast is not a function so you cannot pass its address as the mapped function. You'll have to deal with it.
You cannot use a constructor either.

Code duplication for functions that take shared_ptr and unique_ptr

Problem:
Let's assume I have an algorithm that takes a unique_ptr to some type:
void FancyAlgo(unique_ptr<SomeType>& ptr);
Now I have shared_ptr sPtr to SomeType, and I need to apply the same algorithm on sPtr. Does this mean I have to duplicate the algorithm just for the shared_ptr?
void FancyAlgo(shared_ptr<SomeType>& sPtr);
I know smart pointers come with ownership of the underlying managed object on the heap. Here in my FancyAlgo, ownership is usually not an issue. I thought about stripping off the smart pointer layer and do something like:
void FancyAlgo(SomeType& value);
and when I need to call it with unique_ptr:
FancyAlgo(*ptr);
likewise for shared_ptr.
1, Is this an acceptable style in PRODUCTION code?(I saw somewhere that in a context of smart pointers, you should NOT manipulate raw pointers in a similar way. It has the danger of introducing mysterious bugs.)
2, Can you suggest any better way (without code duplication) if 1 is not a good idea.
Thanks.
Smart pointers are about ownership. Asking for a smart pointer is asking for ownership information or control.
Asking for a non-const lvalue reference to a smart pointer is asking for permission to change the ownership status of that value.
Asking for a const lvalue reference to a smart pointer is asking for permission to query the ownership status of that value.
Asking for an rvalue reference to a smart pointer is being a "sink", and promising to take that ownership away from the caller.
Asking for a const rvalue reference is a bad idea.
If you are accessing the pointed to value, and you want it to be non-nullable, a reference to the underlying type is good.
If you want it to be nullable, a boost::optional<T&> or a T* are acceptable, as is the std::experimental "world's dumbest smart pointer" (or an equivalent hand-written one). All of these are non-owning nullable references to some variable.
In an interface, don't ask for things you don't need and won't need in the future. That makes reasoning about what the function does harder, and leads to problems like you have in the OP. A function that reseats a reference is a very different function from one that reads a value.
Now, a more interesting question based off yours is one where you want the function to reseat the smart pointer, but you want to be able to do it to both shared and unique pointer inputs. This is sort of a strange case, but I could imagine writing a type-erase-down-to-emplace type (a emplace_sink<T>).
template<class T>
using later_ctor = std::function<T*(void*)>;
template<class T, class...Args>
later_ctor<T> delayed_emplace(Args&&...args) {
// relies on C++1z lambda reference reference binding, write manually
// if that doesn't get in, or don't want to rely on it:
return [&](void* ptr)->T* {
return new T(ptr)(std::forward<Args>(args));
};
}
namespace details {
template<class T>
struct emplace_target {
virtual ~emplace_target() {}
virtual T* emplace( later_ctor<T> ctor ) = 0;
};
}
template<class T>
struct emplacer {
std::unique_ptr<emplace_target<T>> pImpl;
template<class...Args>
T* emplace( Args&&... args ) {
return pImpl->emplace( delayed_emplace<T>(std::forward<Args>(args)...) );
}
template<class D>
emplacer( std::shared_ptr<T, D>& target ):
pImpl( new details::emplace_shared_ptr<T,D>(&target) ) // TODO
{}
template<class D>
emplacer( std::unique_ptr<T, D>& target ):
pImpl( new details::emplace_unique_ptr<T,D>(&target) ) // TODO
{}
};
etc. Lots of polish needed. The idea is to type-erase construction of an object T into an arbitrary context. We might need to special case shared_ptr so we can call make_shared, as a void*->T* delayed ctor is not good enough to pull that off (not fundamentally, but because of lack of API hooks).
Aha! I can do a make shared shared ptr without special casing it much.
We allocate a block of memory (char[sizeof(T)]) with a destructor that converts the buffer to T then calls delete, in-place construct in that buffer (getting the T*), then convert to a shared_ptr<T> via the shared_ptr<T>( shared_ptr<char[sizeof(T)]>, T* ) constructor. With careful exception catching this should be safe, and we can emplace using our emplacement function into a make_shared combined buffer.

Resources