Overload regardless noexcept specification - c++

I have to provide an overload set of f, that accepts both member and member function pointers:
void g(int) {}
template <typename T, typename Field>
void f(const T& t, Field T::*field) { g(t.*field); }
template <typename T, typename Field>
void f(const T& t, Field (T::*getter)() const) { g((t.*getter)()); }
struct Foo {
int x = 0;
int y() const noexcept { return 1; }
};
int main() {
const Foo foo;
f(foo, &Foo::x);
f(foo, &Foo::y);
}
This works fine in C++11 and C++14, but breaks in C++17, because as of P0012R1, the noexcept specifier is part of the function type. To resolve this, an additional overload has to be added:
#if __cplusplus >= 201703L
template <typename T, typename Field>
void f(const T& t, Field (T::*getter)() const noexcept) { g((t.*getter)()); }
#endif
The macro guard are necessary, otherwise the code does not compile with older standards, such as C++11 or C++14 (the error is about redefinition of a function template).
As shown above, the implementation of both overloads are the same. Is it possible to provide a single overload that works in C++14 and C++17, without conditional compilation (#if/endif)? The goal is reduction of complexity, code duplication and testing burden.
Actual use case: https://github.com/Morgan-Stanley/binlog/pull/59/files#diff-043a057ac0b43822d0084562ace76697

Yes. Just write the one overload, total, and use std::invoke:
template <typename T, typename F>
void f(const T& t, F f) { g(std::invoke(f, t)); }
While std::invoke itself is C++17, it is implementable in C++11 - and it's probably just worth doing since it's generally useful. This approach not only handles noexcept member functions in C++17, but also reference-qualified and non-const-qualified member functions in C++11.
Although C++11 itself also contains an implementation of std::invoke - just in an unexpected place: std::reference_wrapper<T>:
template <typename T, typename F>
void f(const T& t, F f) { g(std::ref(f)(t)); }

Related

template function overload: enable_if for CRTP, compiler insists on selecting generic function

This is a model case where there is a generic function func and then (humanely speaking) more specialized function func for classes deriving from Base via CRTP, which is only enabled for appropriate argument type via enable_if.
#include<type_traits>
#include<iostream>
// CRTP hierarchy
template<class T> class Base{ };
class Derived: public Base<Derived>{};
// overload 1
template<class T> void func(const T& a){ std::cerr<<"1\n"; }
// overload 2
template<class T, typename std::enable_if<std::is_base_of<Base<T>,T>::value,int>::type* = nullptr>
inline void func(const Base<T>& obj){ std::cerr<<"2\n"; }
int main(void){ func(Derived()); }
The compiler still thinks, however, that the first overload is a better match. I understand that enable_if only enables the function but does not make it better for the overload resolution.
I am sorry to say I was not able to make much sense from Function template section of c++ reference.
Can anyone give an advise how to make compiler prefer the second function?
Thanks!
Edit: MOTIVATION: In the real use, those functions should handle various scalar and array types (Eigen, in particular, which is using CRTP). Scalars should cover all numeric types like ints, floats, ... (without enumerating them) and the other overload should cover arrays — again, without enumerating them, but knowing all of them derive from Eigen::DenseBase<Derived>.
Just use constexpr ifs to select the correct function from a single public function.
C++17
namespace
{
template<typename T>
inline void base_func( const T& derived );
template<typename T>
inline void other_func( const T& otherType );
}
template<typename T>
inline void func( const T& type )
{
if constexpr( std::is_base_of_v<Base<T>, T> )
base_func( type );
else
other_func( type );
}
C++14 Using traits
namespace
{
template<typename T>
inline void base_func( const T& derived );
template<typename T>
inline void other_func( const T& otherType );
template <bool B>
struct func_select_trait;
template <>
struct func_select_trait<true>
{
template <typename T>
static void call( const T& derived ) { base_func<T>( derived ); }
};
template <>
struct func_select_trait<false>
{
template <typename T>
static void call( const T& otherType ) { other_func<T>( otherType ); }
};
}
template<typename T>
inline void func( const T& type )
{
func_select_trait<std::is_base_of<Base<T>, T>::value>::call<T>( type );
}
The 2 overloads are viables
overload 1. has exact match
overload 2. has derived to base conversion
See:
https://en.cppreference.com/w/cpp/language/overload_resolution#Ranking_of_implicit_conversion_sequences for more details
You might SFINAE the first overload:
// overload 1
template <class T, std::enable_if_t<!std::is_base_of_v<Base<T>, T>, int> = 0>
void func(const T& a){ std::cerr<<"1\n"; }
Demo

How to require a C++ template parameter to have some methods with a given signature?

I would like to define a class, which has one template parameter T. I would like to make sure, that T has a void Update(uint32_t) and a int32_t GetResult() const method. I know that the user will get an error when I try to call one of these methods, but I would like to make sure (possibly with a static assert) that they exists as soon as I can.
I was only able to find solutions to check if the class T is derived from some other class U, but that is not what I want. I wold like to allow any class, which has the mentioned methods.
You don't need concepts for this, although those help.
This code will happily works in C++11.
#include <type_traits>
#include <cstdint>
using namespace std;
struct A {
void Update(uint32_t);
int32_t GetResult() const;
};
struct B {
};
using namespace std;
template <typename T, typename = typename enable_if<
is_same<decltype(&T::Update), void (T::*)(uint32_t)>::value &&
is_same<decltype(&T::GetResult), int32_t (T::*)() const>::value
>::type>
struct CLS
{
};
using namespace std;
int main() {
CLS<A> a; // works
CLS<B> b; // fails to compile
return 0;
}
Note, that this code checks exact function signature, so Update(int) won't pass.
EDIT: added const to getResult
With concepts introduced in C++20, this is trivial with requires expressions and requires clauses. In the code, the keyword requires appears twice. The first introduces a requires clause, and the second introduces a requires expression.
template <typename T>
requires requires (T& a, const T& b, uint32_t i) {
a.Update(i);
{b.GetResult()} -> int32_t;
}
void foo(T& x)
{
// ...
}
(live test)
Prior to C++20, you can write a trait class that deploys SFINAE:
template <typename T>
class foo_traits {
static auto check(...) -> std::false_type;
template <typename U>
static auto check(U x) -> decltype((void)x.Update(uint32_t{}), std::true_type{});
public:
static constexpr bool has_update = decltype(check(std::declval<T>()))::value;
};
Now you can use it like:
template <typename T>
void foo(T& x)
{
static_assert(foo_traits<T>::has_update, "blah blah blah");
}
Or:
template <typename T>
std::enable_if_t<foo_traits<T>::has_update> foo(T& x)
{
}
(live test)
GetResult can be handled analogously.
Note: the above code only ensures that the expressions are valid, rather than ensuring the precise signatures. Of course you can also do that. Here's the approach with concepts:
template <typename T>
requires requires (T& a, const T& b, uint32_t i) {
a.Update(i);
{&T::GetResult} -> std::int32_t (T::*)() const;
}
void foo(T& x)
{
// ...
}
Radosław Cybulski's answer already shows how to do this without concepts, so I am not showing it again.
If you want to use a static_assert, that is possible:
static_assert(static_cast< void (T::*)(uint32_t) >(&T::update),
"Need void T::update(uint32_t");
The cast checks if overload resolution is possible, i.e. if the right signature is present.

What does it mean when one says something is SFINAE-friendly?

I can't clearly get the grasp of what it means when one mentions that a particular function, struct or ... is SFINAE-friendly.
Would someone please explain it?
When it allows substitution failure without hard error (as static_assert).
for example
template <typename T>
void call_f(const T& t)
{
t.f();
}
The function is declared for all T, even those which don't have f, so you cannot do SFINAE on call_f<WithoutF> as the method does exist. (Demo of non compiling code).
With following change:
template <typename T>
auto call_f(const T& t) ->decltype(t.f(), void())
{
t.f();
}
The method exists only for valid T.
so you can use SFINAE as
template<typename T>
auto call_f_if_available_impl(const T& t, int) -> decltype(call_f(t))
{
call_f(t);
}
template<typename T>
auto call_f_if_available_impl(const T& t, ...)
{
// Do nothing;
}
template<typename T>
auto call_f_if_available(const T& t)
{
call_f_if_available_impl(t, 0);
}
Note the int = 0 and ... is to order the overload.
Demo
--
An other case is when the template add special parameter to apply SFINAE for specialization:
template <typename T, typename Enabler = void> struct S;
And then
// Specialization only available for T which respect the traits.
template <typename T>
struct S<T, std::enable_if_t<my_type_trait<T>::value>>
{
};
An entity is termed SFINAE-friendly if it can be used in the context of SFINAE without producing a hard error upon substitution failure. I assume you already know what SFINAE is, as that is a whole other question in itself.
In the context of C++ standardization, the term SFINAE-friendly has so far been applied to std::result_of and std::common_type. Take the following example:
template <typename T>
void foo(T x, typename std::common_type<T, int>::type y) {}
void foo(std::string x, std::string y) {}
int main()
{
foo(std::string("hello"), std::string("world"));
}
Without SFINAE-friendly common_type, this would fail to compile, because std::common_type<std::string, int>::type would produce a hard error during template argument substitution. With the introduction of SFINAE-friendly common_type (N3843) this example becomes well-formed, because std::common_type<std::string, int>::type produces a substitution failure so that overload is excluded from the viable set.
Here's a similar example with result_of:
template <typename T>
auto bar(T f) -> typename std::result_of<T()>::type { return f(); }
void bar(int n) {}
int main()
{
bar(42);
}
Without SFINAE-friendly result_of, this would fail to compile, because std::result_of<int()>::type would produce a hard error during template argument substitution. With the introduction of SFINAE-friendly result_of (N3462) this example becomes well-formed, because std::result_of<int()>::type produces a substitution failure so that overload is excluded from the viable set.

SFINAE: std::enable_if as function argument

So, I'm following the example set by the code somewhere on this web page:
http://eli.thegreenplace.net/2014/sfinae-and-enable_if/
Here's what I have:
template<typename T>
void fun(const typename std::enable_if_t<std::is_integral<T>::value, T>& val) {
std::cout << "fun<int>";
}
template<typename T>
void fun(const typename std::enable_if_t<std::is_floating_point<T>::value, T>& val) {
std::cout << "fun<float>";
}
int main()
{
fun(4);
fun(4.4);
}
This way I would have to write:
fun<int>(4);
fun<double>(4.4);
How would I avoid that?
Compiler complains that it can't deduce the parameter T.
The examples are wrong, since T is in a non-deduced context. Unless you call the function like fun<int>(4);, the code won't compile, but this is probably not what the author intended to show.
The correct usage would be to allow T to be deduced by the compiler, and to place a SFINAE condition elsewhere, e.g., in a return type syntax:
template <typename T>
auto fun(const T& val)
-> typename std::enable_if<std::is_integral<T>::value>::type
{
std::cout << "fun<int>";
}
template <typename T>
auto fun(const T& val)
-> typename std::enable_if<std::is_floating_point<T>::value>::type
{
std::cout << "fun<float>";
}
DEMO
Also, the typenames in your code contradict your usage of std::enable_if_t.
Use either c++11:
typename std::enable_if<...>::type
or c++14:
std::enable_if_t<...>
How would that work in a constructor which doesn't have a return type though?
In case of constructors, the SFINAE condition can be hidden in a template parameter list:
struct A
{
template <typename T,
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
A(const T& val)
{
std::cout << "A<int>";
}
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
A(const T& val)
{
std::cout << "A<float>";
}
};
DEMO 2
Alternatively, in c++20, you can use concepts for that:
A(const std::integral auto& val);
A(const std::floating_point auto& val);
To allow deduction you need a function parameter that is straightforwardly based on T. You then need to figure out where to put your enable_if (which indeed does not allow T to be deduced). Common options are on the return type or on an extra default parameter that you ignore.
Some good examples here: http://en.cppreference.com/w/cpp/types/enable_if

decltype comparison

Is there a way to compare the result of decltype in C++11?
In other words, why is this code invalid:
template<typename T, typename U>
void func(T& t, U& u) {
if(decltype(t) == decltype(u)) {
// Some optimised version for this case
} else {
// A more general case for differing types
}
}
I know that in some cases this particular problem can be solved by partial template specialisation; my question is about comparison of decltypes.
Edit: The question came up in the course of trying to provide defaults for free functions through SFINAE. Perhaps a better question would have been why this is invalid:
template<bool B>
bool SomeFunction() { ... }
template<typename T, typename U>
bool SomeFunctionWrapper(T& t, U& u) {
SomeFunction<decltype(t) == decltype(u)>();
}
I've since found another solution (that doesn't involve templates at all) but at one stage I tried this:
// If it exists, the free function is defined as
// bool AFreeFunction();
typedef struct { char } undefined;
template<typename T = void>
undefined AFreeFunction();
template<bool B>
bool AFreeFunctionWrapper_() {
return false;
}
template<>
bool AFreeFunctionWrapper_<false>() {
return AFreeFunction();
}
bool AFreeFunctionWrapper() {
return AFreeFunctionWrapper_<decltype(AFreeFunction()) == decltype(undefined)>();
}
I eventually got a variant of this strategy working with GCC 4.6, but then discovered that default template arguments are not allowed for template functions in MSVC, even in the 2012 RC. So the eventual solution looks like this:
class AFreeFunction {
public:
operator bool() { return false; }
};
If the function is defined, it gets called. If it's not, it is instead interpreted as a constructor for the class, which is then implicitly cast to bool.
You normally solve this problem through tag dispatching. Also, you already have the "declared type" of t and u - T& and U&, respectively. To compare types for equality, you can use std::is_same. However, overload resolution already solves this problem for you:
template<class T>
void f(T& v1, T& v2){ ... } // #1
template<class T, class U>
void f(T& t, U& u){ ... } // #2
#1 is more specialized than #2 if both arguments to f are of the same type. If you, for whatever reason, insist on solving this through manual type comparision, here's how it would look applying the before mentioned points:
#include <type_traits>
namespace detail{
template<class T, class U>
void f(T& t, U& u, std::true_type){ ... } // #1
template<class T, class U>
void f(T& t, U& u, std::false_type){ ... } // #2
} // detail::
template<class T, class U>
void f(T& t, U& u){
detail::f(t, u, std::is_same<T,U>()); // tag dispatching
}
std::is_same will derive from std::true_type if both types are the same, and from std::false_type if not.
Why is it invalid? The result of a decltype is, well, a type. So it's saying something like
if (int == int)
which the language obviously doesn't allow.
You'll need to separate the two parts of the function and put the specialized part inside a function in a specialized class, and forward the call there. It's painful.
Or, you could use typeid or run-time type information, if your implementation implements it correctly, although that will defer everything to when the program runs (which allows for fewer optimizations).
You can do this using SFINAE (std::enable_if):
template<typename T, typename U>
typename std::enable_if<std::is_same<T, U>::value, void>::type func(T& t, U& u) {
std::cout << "same\n";
}
template<typename T, typename U>
typename std::enable_if<!std::is_same<T, U>::value, void>::type func(T& t, U& u) {
std::cout << "different\n";
}
As Mehrdad says, decltype(t) and decltype(u) are types (T & and U & respectively), not values, so cannot be compared at value-expression level but must be compared at meta-expression (template) level.