Reputation: 5772
We have:
template<typename T>
struct A {
void foo(int a) {
T::foo(a);
}
};
template<typename T>
struct B {
template struct A<T>; // concept check
};
So, I define a concept checker A that checks T by forwarding foo to T::foo.
Now, I want to check whether the argument passed to B satisfies the concept A by explicit instantiation, but the compiler complains that it's the wrong namespace. How can I fix that?
Upvotes: 0
Views: 103
Reputation: 5772
So, I found a working example:
#include <tuple>
template<typename A>
struct IA : A {
void foo(int a) {
A::foo(a);
}
void bar(double a) {
A::bar(a);
}
static constexpr auto $ = std::make_tuple(&IA::foo, &IA::bar);
};
template<typename T>
struct B {
// trigger concept/interface check of T "implements" IA
static constexpr auto $ = IA<T>::$;
};
struct Test {
void foo(int a) {}
void bar(int a, int b) {}
};
int main() {
B<Test> b;
b = b;
}
The generation of $ in the structs triggers the compilation. The compiler in the example above correctly complains with:
In instantiation of 'void IA<A>::bar(double) [with A = Test]':
13:57: required from 'constexpr const std::tuple<void (IA<Test>::*)(int), void (IA<Test>::*)(double)> IA<Test>::$'
18:27: recursively required from 'constexpr const std::tuple<void (IA<Test>::*)(int), void (IA<Test>::*)(double)> B<Test>::$'
18:27: required from 'struct B<Test>'
28:13: required from here
10:17: error: no matching function for call to 'IA<Test>::bar(double&)'
10:17: note: candidate is:
24:10: note: void Test::bar(int, int)
24:10: note: candidate expects 2 arguments, 1 provided
Upvotes: 0
Reputation: 52471
Something like this perhaps:
template<typename T, void(T::*)(int)>
struct A {};
template<typename T>
struct B {
using Check = A<T, &T::foo>;
};
Or this:
template<typename T>
struct B {
static_assert(
std::is_same<decltype(&T::foo), void(T::*)(int)>::value,
"No T::foo(int) member");
};
Upvotes: 1