Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何强制实例化类模板的成员函数?_C++_C++11_Templates_Sfinae - Fatal编程技术网

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

C++ 如何强制实例化类模板的成员函数?,c++,c++11,templates,sfinae,C++,C++11,Templates,Sfinae,我最近发现类模板的成员函数在被使用之前是不会被实例化的,这是非常令人讨厌的,因为它使得某些SFINAE构造无法工作。我想知道如何确保一个类模板专门化的成员函数总是在类被实例化时就被实例化——但只使用类模板定义中的语句,这样如果成员函数不能被实例化,SFINAE启动,编译器依赖于通用类模板 我计划使用的代码如下所示: template <typename T, typename U> class test_type { // general template; dummy pa

我最近发现类模板的成员函数在被使用之前是不会被实例化的,这是非常令人讨厌的,因为它使得某些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;
模板
类测试类型{
//通用模板;伪参数U允许专门化。
静态常量布尔值=假;
}
模板
类测试类型{
//模板专门化
空隙f(T){
//使用t执行各种类型特定的操作
//(例如,调用成员函数)
//如果T不适合这些操作,我希望
//要生成的替换错误,以便
//改为使用通用模板
}
静态常量布尔值=真;
}
模板
使用满足=测试类型::值;

类中的成员函数体不属于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{});
}
#包括
#包括
模板
使用check\u for\u method=std::void\t;
模板
类测试类型{
公众:
静态常量布尔值=假;
};
模板
类测试类型{
公众:
空隙f(T){
t、 run();
t、 go();
}
静态常量布尔值=真;
};
结构Foo{
无效运行(){

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

您需要做的是构建一个类型_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{});
}
#包括
#包括
模板
使用check\u for\u method=std::void\t;
模板
类测试类型{
公众:
静态常量布尔值=假;
};
模板
类测试类型{
公众:
空隙f(T){
t、 run();
t、 go();
}
静态常量布尔值=真;
};
结构Foo{
无效运行(){

std::cout什么是SFINAE构造的?我知道的那些依赖于这些成员函数的声明,这些成员函数在类被初始化时被实例化。您尝试执行的一些代码将是有用的。SFINAE在声明上工作,实际上不需要定义…更少的描述和更多的代码。@Anonymous1847-我不懂。如果
还不足以说明
f
可以调用且在实例化时格式良好,您的库中有一个bug。强制实例化格式错误的
f
不会在SFINAE上下文中导致静默替换失败,这将是一个硬错误。SFINAE构造了什么?我知道的那些构造取决于se成员函数,当类为时实例化。您尝试执行的某些代码将非常有用。SFINAE用于声明,定义实际上并不需要…更少的描述和更多的代码。@Anonymous1847-我不这么认为。如果仅
不足以说明可以调用
f
,并且可以很好地rmed实例化时,库中有一个bug。强制实例化格式错误的
f
不会导致SFINAE上下文中的静默替换失败,这将是一个硬错误。