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.
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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With