Is requires(std::derived_from<...>) equivalent to static_assert(std::is_base_of<...>)?

548 Views Asked by At

I'm attempting to learn requires expressions as a stepping stone towards getting comfortable with the concepts mechanic. The easiest way I could come up with was to ease into it by replacing all my static_assert expressions in any templates with requires expressions.

One that is a little tricky to understand is the difference between std::is_base_of_v<> and std::derived_from<>.

Are the following requires and static_assert expressions equivalent, i.e., do the same thing? If not, what will? My intent was to require, after any possible reference/cv/pointer decoration was removed, that GameType and GameBase were derived from each other:

class GameBase {
//...
};

//...

#include <concepts>
#include <string>
#include <type_traits>

template<typename GameType>
requires(std::derived_from<GameType, GameBase>)
class Engine {
public:
    static_assert(std::is_base_of_v<std::remove_cvref_t<std::remove_pointer_t<GameBase>>, std::remove_cvref_t<std::remove_pointer_t<GameType>>>, "GameType template parameter is not derived from GameBase.");
    static void Initialize(const std::string& title, const std::string& cmdString) noexcept;
    static void Run() noexcept;
    static void Shutdown() noexcept;
    static const bool Available() noexcept;

private:
    static inline bool m_initCalled{false};
    static inline bool m_shutdownCalled{false};
};
1

There are 1 best solutions below

9
macomphy On

Here is an example that answer your question.

#include <type_traits>
#include <concepts>

template <typename T>
struct foo;

template <typename T>
requires(std::same_as<T, int>)
struct foo<T>{};

template <typename T>
requires(std::same_as<T, double>)
struct foo<T>{};

template <typename T>
struct bar;

/// error, static_assert cannot be used as specilization
/*
template <typename T>
struct bar<T>{
    static_assert(std::is_same_v<int, T>);
};

template <typename T>
struct bar<T>{
    static_assert(std::is_same_v<double, T>);
};
*/