I have several structs in the form
struct MyStruct1 {
  std::string myName;
  // ...
}
but not all of them have a member of type std::string and variable named myName.
I'm writing a function template, but I want to restrict access to it, so that only structs that possess this field myName can be passed to the function.
So far, I just tried:
template <typename T>
concept allowedInputType = std::same_as<T, MyStruct1> || std::same_as<T, MyStruct2>; // and so forth
but is there a more elegant way?
If you want to make sure the type has a myName member which is a std::string (or similar), you can define a concept like this:
#include <concepts>
#include <string>
template<typename T>
concept has_myName_string_member = requires {
    { T::myName } -> std::convertible_to<std::string>;
};
Then use it as following:
template <has_myName_string_member T>
void foo([[maybe_unused]] T const& t) {
}
struct S1 {
    std::string myName;
};
struct S2 {
    int myName;
};
struct S3 {
    int a;
};
int main() {
    foo(S1{});
    //foo(S2{});  // MSVC error: error C2672: 'foo': no matching overloaded function found
    //foo(S3{});  // MSVC error: error C2672: 'foo': no matching overloaded function found
}
Live demo 1
Note:
If you want to specify that myName member must be exactly a std::string (and not anything convertible to one), you can use std::same_as<std::string&> instead of std::convertible_to<std::string> in the requires expression of the concept.
If on the other hand you wish to require only the existance of a member by name (but it can be of any type), you can use this concept:
template<typename T>
concept has_myName_member = requires {
    T::myName;
};
And now the above S2 will be accepted (but not S3).
Live demo 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With