У меня есть следующий отрезанный код, который не компилируется.
#include <iostream>
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
template<typename U, U> struct helper{};
int main() {
helper<void (A::*)(), &A::foo> compiles;
helper<void (B::*)(), &B::foo> does_not_compile;
return 0;
}
Он не компилируется, так как &B::foo
разрешает &A::foo
и, следовательно, не может соответствовать предлагаемому типу void (B::*)()
. Поскольку это часть шаблона SFINAE, который я использую для проверки очень специфического интерфейса (я заставляю конкретные типы аргументов и типы вывода), я хотел бы, чтобы это работало независимо от наследования, сохраняя при этом чек читабельным.
То, что я пробовал, включает в себя:
-
Отбрасывание второй части аргумента:
helper<void (B::*)(), (void (B::*)())&B::foo> does_not_compile;
Это, к сожалению, не помогает, поскольку вторая часть теперь не распознается как постоянное выражение и не выполняется.
-
Я попытался назначить ссылку на переменную, чтобы проверить это.
constexpr void (B::* p)() = &B::foo; helper<void (B::* const)(), p> half_compiles;
Этот код принят clang 3.4, но g++ 4.8.1 отвергает его, и я понятия не имею, кто прав.
Любые идеи?
EDIT: поскольку многие комментарии запрашивают более конкретную версию проблемы, я напишу ее здесь:
То, что я ищу, - это способ явно проверить, что класс относится к определенному интерфейсу. Эта проверка будет использоваться для проверки входных аргументов в шаблонных функциях, чтобы они соблюдали контракт, который требуются этим функциям, поэтому компиляция останавливается заранее, если класс и функция несовместимы (т.е. Тип типа типа проверки).
Таким образом, мне нужно иметь возможность проверять тип возвращаемого значения, тип аргумента и число, константу и т.д. каждой функции-члена, которую я запрашиваю. Первоначальный вопрос был проверкой части большего шаблона, который я использую для проверки совпадений.