如何强制实例化类模板的成员函数?

Ano*_*847 0 c++ templates sfinae c++11

我最近发现类模板的成员函数在使用之前不会被实例化,这非常烦人,因为它使某些SFINAE结构不起作用.我想知道如何确保在实例化类之后始终实例化类模板特化的成员函数 - 但仅使用类模板定义中的语句,以便在成员函数无法实例化时,SFINAE启动并且编译器回退到通用类模板.

我打算使用的代码如下所示:

template <typename T, typename U>
class test_type {
    // general template; dummy parameter U is to allow specialization.
    static const bool value = false;
}

template <typename T>
class test_type<T, T> {
    // template specialization
    void f(T t) {
        // do all sorts of type-specific operations with t
        // (e.g., calling member functions)

        // if T is not suitable for these operations, I want
        // a substitution error to be generated so that the
        // general template is used instead
    }

    static const bool value = true;
}

template <typename T>
using satisfies = test_type<T, T>::value;
Run Code Online (Sandbox Code Playgroud)

sup*_*per 5

类中的成员函数的主体将不是SFINAE的一部分.模板根据签名进行实例化,一旦实例化了类,错误的成员函数将导致硬错误.

您需要做的是构建一个可以放在模板特化中的type_trait.这是一个检查两个不同成员函数的玩具示例.

#include <iostream>
#include <type_traits>

template <typename T>
using check_for_method = std::void_t<decltype(std::declval<T>().run()), decltype(std::declval<T>().go())>;

template <typename T, typename U = void>
class test_type {
public:
    static const bool value = false;
};

template <typename T>
class test_type<T, check_for_method<T>> {
public:
    void f(T t) {
        t.run();
        t.go();
    }

    static const bool value = true;
};

struct Foo {
    void run() {
        std::cout << "Running\n";
    }
};

struct Bar : Foo {
    void go() {
        std::cout << "Going\n";
    }
};

int main() {
    test_type<Foo> t1;
    test_type<int> t2;
    test_type<Bar> t3;

    std::cout << t1.value << " " << t2.value << " " << t3.value << std::endl;
    t3.f(Bar{});
}
Run Code Online (Sandbox Code Playgroud)