Variadic template aliases or functions? - c++11

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.

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*.

Wouldn't it make sense to overload with respect to noexcept?

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.

Conversion operator overloads for l-values, avoid repeated code

I have a wrapper class that needs to be used interchangeably with the wrapped class.
Fortunately the class and the wrapper are binary compatible (by design) and the conversion can be easily performed (for example in this case by reinterpret_cast, or even simpler as in the example).
In part, to achieve this, I need to be able to convert from the wrapper type to the wrapped type, via operator T().
Currently the code looks like this:
template<class T> // // I am putting this general T type, to show it can be a large (movable) object, for example, std::vector.
struct wrapper{
T a;
operator T const&() const&{return a;} // in other cases it can involve more code, like reinterpret_casts or some conditional blocks.
operator T&&() &&{return std::move(a);} // same
operator T&() &{return a;} // same
};
Can I condense these three conversion functions into one function or less code, or is there another way?
I could make it more general, (but longer code for this simple case) this way,
template<class T>
struct wrapper{
T a;
operator T const&() const&{return a;} // complicated code can be here only
operator T&&() &&{return std::move(operator A&());}
operator T&() &{return const_cast<T&>(operator T const&());}
};
The final objective is that T can be used interchangeably with wrapper<T>.
This is very similar to How do I remove code duplication between similar const and non-const member functions?,
however this case is more specific because 1) it involves the conversion operator and also, 2) involves l-value overloads.

std forward implementation and reference collapsing

in scott meyers book he mentioned an implementation for std forward that goes like this (non std conformant)
template <typename T>
T&& forward(typename remove_reference<T>::type& param)
{
return static_cast<T&&>(param);
}
The question is why do we need to remove reference here?
so a typical forward usage would be in a universal reference function as follows:
template <typename T>
void f(T&& fparam)
{
g(forward<T>(fparam)); // assume there is g function.
}
without remove reference, the forward would look like this
template <typename T>
T&& forward(T& param);
now the two cases are:
fparam is rvalue in that case inside f function the T is deduced as
non reference object type so the forward call take the param by
lvalue reference and cast it to T&& (because T is non reference).
fparam is lvalue then inside f the T is deduced as T& then forward
will take (as argument) a reference to an lvalue reference (collapsing to lvalue
reference) then the static cast would be T& && which is again lvalue
reference.
so why do we need to remove reference from param of forward? does it have to do with disallowing deducing types maybe? can somebody maybe give a detailed explanation.
The question that is referenced as duplicate is not, the answer basically says that the std library uses remove reference but why?
Does it have to do with disallowing deducing types maybe?
Yes, typename std::remove_reference<T>::type introduces a non-deduced context. It prevents the user from mistakenly writing...
std::forward(something)
...and forces him/her to provide an explicit template argument:
std::forward<T>(something)

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.

Resources