I have a type trait and concept which checks if an std::variant can hold a given type T. Now I have a type variant2 which derives from std::variant, and I want to use that type trait with the new variant2 type. How can I accomplish this elegantly?
This doesn't work (Demo):
#include <variant>
#include <string>
#include <iostream>
#include <concepts>
#include <type_traits>
template<typename T, typename Variant>
struct variant_type;
template<typename T, typename... Args>
struct variant_type<T, std::variant<Args...>>
: public std::disjunction<std::is_same<T, Args>...> {};
template<typename T, typename Variant>
concept is_variant_type = variant_type<T, Variant>::value;
template <typename... Ts>
struct variant2 : public std::variant<Ts...> {
};
variant2<std::monostate, int, bool, std::string> var;
int main() {
using T = std::string;
if constexpr (is_variant_type<T, decltype(var)>) {
std::cout << "Worked!" << std::endl;
}
}
"Worked" never appears on the screen which is obvious because the default type trait is SFINAED.
You can just fix your specialization by expressing that your template must inherit from
std::variantI just added a conjunction to achieve that and we'are done.
Live
[EDIT] sorry, it's just a bit more complicated: I added a template template parameter that implies that your inherited class has exactly the same template parameters than the base one, which might be restrictive.