I have a template that is intended to take int, float, double, char and std::string.
I want a method to only exist if the template typename is std::string
Is this possible?
>Solution :
If you can use C++20, you can use a requires expression on the desired method to cause it to only be available under certain circumstances.
#include <iostream>
#include <string>
#include <concepts>
template<class T>
struct Foo
{
void alwaysAvailable() { std::cout << "Always available\n"; }
void conditionallyAvailable() requires std::same_as<T, std::string>
{
std::cout << "T is std::string\n";
}
};
int main()
{
Foo<int> fooInt;
fooInt.alwaysAvailable();
//fooInt.conditionallyAvailable(); // Constraint not satisfied
Foo<std::string> fooString;
fooString.alwaysAvailable();
fooString.conditionallyAvailable();
}
Foo<T>::alwaysAvailable is, as the name suggests, always available no matter what T is. Foo<T>::conditionallyAvailable is only available when T is std::string.
The C++17 version is a little uglier. We have to make conditionallyAvailable a method template and then place some SFINAE constraints on the method:
#include <type_traits>
template<class T>
struct Foo
{
void alwaysAvailable() { std::cout << "Always available\n"; }
template<class U = T>
std::enable_if_t<std::is_same_v<U, T> && std::is_same_v<U, std::string>, void> conditionallyAvailable()
{
std::cout << "T is std::string\n";
}
};
C++14 and C++11 versions are similar to the C++17 version except for needing to expand out enable_if_t and is_same_v.