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