#include <iostream>
#include <concepts>
#include <string>
// Define concepts here
template <typename Callable, typename... Args>
concept callable_with_args = std::invocable<Callable, Args...>;
template <typename Callable, typename Return, typename... Args>
concept callable_with_return = requires(Callable func, Args... args) {
{ func(args...) } -> std::same_as<Return>;
};
// Implement CallbackValidator class here
template <typename Callable, typename Return, typename... Args>
class CallbackValidator {
public:
CallbackValidator(Callable func) : callable(func) {}
// The validation member function
void validate() {
static_assert(callable_with_args<Callable, Args...>, "Invalid argument types");
static_assert(callable_with_return<Callable, Return, Args...>, "Invalid return type");
std::cout << "The object is compatible.\n";
}
private:
Callable callable;
};
// Class definition for example usage
struct Concatenator {
std::string operator()(char a, char b) const {
return std::to_string(a) + std::to_string(b);
}
};
int main() {
// Performing the validation check for lambda function
auto add = [](int a, int b) { return static_cast<double>(a + b); };
CallbackValidator<decltype(add), double, int, int> validator1(add);
validator1.validate();
// Performing the validation check for Concatenator class
Concatenator concatenator;
CallbackValidator<Concatenator, std::string, char, char> validator2(concatenator);
validator2.validate();
return 0;
}