用于概念检查的显式实例化

Explicit instantiation for concept checking

我们有:

template<typename T>
struct A {
  void foo(int a) {
    T::foo(a);
  }
};

template<typename T> 
struct B {
  template struct A<T>; // concept check
};

因此,我定义了一个概念检查器 A,它通过将 foo 转发到 T::foo 来检查 T。

现在,我想通过显式实例化检查传递给 B 的参数是否满足概念 A,但编译器抱怨它是错误的命名空间。我该如何解决?

也许是这样的:

template<typename T, void(T::*)(int)>
struct A {};

template<typename T> 
struct B {
  using Check = A<T, &T::foo>;
};

Demo


或者这样:

template<typename T> 
struct B {
  static_assert(
    std::is_same<decltype(&T::foo), void(T::*)(int)>::value,
    "No T::foo(int) member");
};

所以,我找到了一个工作示例:

#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;
}

structs中$的生成触发编译。上面示例中的编译器正确地抱怨:

 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