Я искал код шаблона, который отвечает на вопрос "имеет ли класс T член X?".В Интернете есть некоторые решения, в которых используется SFINAE (например, см. Как определить, существует ли конкретная переменная-член в классе? ), но у всех них есть недостаток, заключающийся в том, что имя члена X жестко закодировано.в решении.Поэтому я создал макрос DECL_HAS_MEMBER (member_name), который объявляет необходимые классы шаблонов, которые проверяют член "member_name":
#define DECL_HAS_MEMBER(member_name) \
template<typename T, typename = void> struct has_member_##member_name : std::false_type {}; \
template<typename T> \
struct has_member_##member_name<T, decltype((void)T::member_name, (void)0)> : std::true_type {}; \
template<typename T> constexpr auto has_member_##member_name##_v = has_member_##member_name<T>::value;
Теперь я могу использовать следующий код:
DECL_HAS_MEMBER(test)
...
bool has_test = has_member_test_v<MYCLASS>;
(Примечание: фактически, я немного усовершенствовал этот код, чтобы выяснить, является ли «test» статическим целочисленным элементом данных.)
Проблема возникает, когда у меня два вызова «DECL_HAS_MEMBER (test)» в одном и том жеблок перевода, например, через различные включенные заголовочные файлыКомпилятор MSVC выдает следующие сообщения об ошибках:
warning C4348: 'has_member_test': redefinition of default parameter: parameter 2
error C2953: 'has_member_test': class template has already been defined
error C2976: 'has_member_test': too few template arguments
error C2086: 'const auto has_member_test_v': redefinition
Хотя я понимаю, что компилятор не хочет видеть два (хотя и идентичных) определения шаблона или переменной, я не вижу, как решитьэта проблема.Защита от включения явно не поможет, потому что это не заголовочный файл, на который жалуется компилятор.
Есть идеи?