Last active
September 29, 2023 16:06
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice primer