I'd like to have a C++ concept that matches a particular template type regardless of one of the template arguments. I can, of course, do this using some other helper declarations to pick apart the template type. But one of the benefits of concepts and requires expressions in particular is that they eliminate many of the needs for helper types. So I'm wondering if it's possible to do this "all-in-one" with a single concept declaration.
Here's a minimal working example:
#include <algorithm>
#include <compare>
#include <iostream>
#include <memory>
#include <string>
template<typename A> using char_string =
std::basic_string<char, std::char_traits<char>, A>;
using std::string;
template<typename T> struct AltAllocator : std::allocator<T> {};
using AltString = char_string<AltAllocator<char>>;
template<typename T> constexpr bool is_char_string_v = false;
template<typename A> constexpr bool is_char_string_v<char_string<A>> = true;
template<typename T> concept is_char_string = is_char_string_v<T>;
inline bool
operator==(is_char_string auto const &a, is_char_string auto const &b)
{
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
int
main()
{
string s;
AltString as;
std::cout << std::boolalpha << (s == as) << std::endl;
}
I'm hoping to be able to define is_char_string
without having to introduce is_char_string_v
. In this particular case, knowing that strings contain their allocator type, I could of course "cheat" with something like this:
template<typename T> concept is_char_string =
std::same_as<T, char_string<typename T::allocator_type>>;
Is there a more general way of writing a self-contained concept that matches some particular template instantiated with any template arguments?