Skip to content

Instantly share code, notes, and snippets.

@KillerGoldFisch
Last active September 29, 2023 16:06
Show Gist options
  • Save KillerGoldFisch/ce4f77eec3cd17bf9ec5f0e52df470c5 to your computer and use it in GitHub Desktop.
Save KillerGoldFisch/ce4f77eec3cd17bf9ec5f0e52df470c5 to your computer and use it in GitHub Desktop.
Example for a conditional template definition, where the compiler distinguishes between types that define a static method or not.
#include <iostream>
#include <type_traits>
// Helper Struct for checking the existence of the static method.
// This struct defaults to std::false_type (indicating the method does not exist)
template <typename T, typename = void>
struct has_static_method : std::false_type {};
// Specialization of has_static_method for types T that do have a static_method.
// The std::void_t<decltype(T::static_method())> is a void type if T::static_method() is a valid expression,
// thus this specialization is chosen when T has a static_method, inheriting from std::true_type (indicating the method exists).
template <typename T>
struct has_static_method<T, std::void_t<decltype(T::static_method())>> : std::true_type {};
// Classes with and without static method for demonstration
class WithStaticMethod {
public:
static void static_method() { std::cout << "Static method called" << std::endl; }
};
class WithoutStaticMethod {};
// Helper template function to call the static method if it exists.
// This function overload is chosen when T has a static_method (has_static_method<T> is std::true_type).
template <typename T>
auto call_static_method(int value, std::true_type) -> decltype(T::static_method(), void()) {
std::cout << "Integer value: " << value << std::endl;
T::static_method();
}
// Overload of the call_static_method function that is executed when no static method is present.
// This function overload is chosen when T does not have a static_method (has_static_method<T> is std::false_type).
template <typename T>
void call_static_method(int value, std::false_type) {
std::cout << "Integer value: " << value << std::endl;
std::cout << "No static method found" << std::endl;
}
// This function serves as an entry point to direct to the appropriate call_static_method overload based on whether T has a static_method.
template <typename T>
void call_static_method(int value) {
call_static_method<T>(value, has_static_method<T>{}); // Dispatches to the correct overload based on the value of has_static_method<T>.
}
int main() {
call_static_method<WithStaticMethod>(42); // Outputs the integer value and "Static method called" since WithStaticMethod has a static_method.
call_static_method<WithoutStaticMethod>(42); // Outputs the integer value and "No static method found" since WithoutStaticMethod does not have a static_method.
return 0;
}
#include <iostream>
#include <type_traits>
// Helper struct to check for the existence of the static method.
template <typename T, typename = void>
struct has_static_method : std::false_type {};
template <typename T>
struct has_static_method<T, std::void_t<decltype(T::static_method())>> : std::true_type {};
// Classes with and without static method for demonstration.
class WithStaticMethod {
public:
static void static_method() { std::cout << "Static method called" << std::endl; }
};
class WithoutStaticMethod {};
// Function to call the static method if it exists.
template <typename T>
void call_static_method(int value) {
std::cout << "Integer value: " << value << std::endl;
// Check if T has a static_method using if constexpr and call it if it exists.
if constexpr (has_static_method<T>::value) {
T::static_method();
}
else {
std::cout << "No static method found" << std::endl;
}
}
int main() {
call_static_method<WithStaticMethod>(42); // Outputs the integer value and "Static method called" since WithStaticMethod has a static_method.
call_static_method<WithoutStaticMethod>(42); // Outputs the integer value and "No static method found" since WithoutStaticMethod does not have a static_method.
return 0;
}
#include <iostream>
#include <type_traits>
// Adjusted helper struct to check for the existence of the static method with a specified signature.
template <typename T, typename Arg, typename Ret, typename = void>
struct has_static_method : std::false_type {};
template <typename T, typename Arg, typename Ret>
struct has_static_method<T, Arg, Ret, std::void_t<decltype(T::static_method(std::declval<Arg>()))>>
: std::is_same<Ret, decltype(T::static_method(std::declval<Arg>()))> {};
// Classes with and without static method for demonstration.
class WithStaticMethod {
public:
static int static_method(int arg) {
std::cout << "Static method called with arg: " << arg << std::endl;
return arg * 2;
}
};
class WithoutStaticMethod {};
// Function to call the static method if it exists.
template <typename T, typename Arg>
auto call_static_method(Arg arg) -> std::enable_if_t<has_static_method<T, Arg, int>::value, int> {
std::cout << "Argument value: " << arg << std::endl;
return T::static_method(arg);
}
// Overload for when static_method does not exist.
template <typename T, typename Arg>
auto call_static_method(Arg arg) -> std::enable_if_t<!has_static_method<T, Arg, int>::value, int> {
std::cout << "Argument value: " << arg << std::endl;
std::cout << "No static method found" << std::endl;
return -1; // Return some default or error value.
}
int main() {
int result1 = call_static_method<WithStaticMethod>(42); // Outputs the argument value and "Static method called with arg: 42" since WithStaticMethod has a static_method.
std::cout << "Result: " << result1 << std::endl; // Outputs "Result: 84"
int result2 = call_static_method<WithoutStaticMethod>(42); // Outputs the argument value and "No static method found" since WithoutStaticMethod does not have a static_method.
std::cout << "Result: " << result2 << std::endl; // Outputs "Result: -1"
return 0;
}
#include <iostream>
#include <type_traits>
// Helper struct to check for the existence of the static method with a specified signature.
template <typename T, typename Arg, typename Ret, typename = void>
struct has_static_method : std::false_type {};
template <typename T, typename Arg, typename Ret>
struct has_static_method<T, Arg, Ret, std::void_t<decltype(T::static_method(std::declval<Arg>()))>>
: std::is_same<Ret, decltype(T::static_method(std::declval<Arg>()))> {};
// Classes with and without static method for demonstration.
class WithStaticMethod {
public:
static int static_method(int arg) {
std::cout << "Static method called with arg: " << arg << std::endl;
return arg * 2;
}
};
class WithoutStaticMethod {};
// Function to call the static method if it exists.
template <typename T, typename Arg>
auto call_static_method(Arg arg) {
std::cout << "Argument value: " << arg << std::endl;
if constexpr (has_static_method<T, Arg, int>::value) {
return T::static_method(arg);
}
else {
std::cout << "No static method found" << std::endl;
return -1; // Return some default or error value.
}
}
int main() {
int result1 = call_static_method<WithStaticMethod>(42); // Outputs the argument value and "Static method called with arg: 42" since WithStaticMethod has a static_method.
std::cout << "Result: " << result1 << std::endl; // Outputs "Result: 84"
int result2 = call_static_method<WithoutStaticMethod>(42); // Outputs the argument value and "No static method found"
}
@KillerGoldFisch
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment