简体   繁体   English

关于类模板部分特化和类成员特化的一些令人困惑的事情

[英]something confusing about class template partial specialization & class member specialization

Here I define a class template Foo, specialize its member function, and then supply a partial specialization for that class: 在这里,我定义了一个类模板Foo,专门化它的成员函数,然后为该类提供部分特化:

// this is Foo_0
template<typename T, typename S>
class Foo {
public:
    void operator()() {
        std::cout << "Foo_0\n";
    }
    template<typename R>
    void bar(R) {
        std::cout << "I'm from Foo_0\n";
    }
};
template<>
template<>
void Foo<double, int>::bar(double) {
    std::cout << "Now I'm specialized!\n";
}

// this is Foo_1
template<typename T>
class Foo<T, int> {
public:
    void operator()() {
        std::cout << "Foo_1\n";
    }
};

And I instantiate Foo on VS2015 like this: 我在VS2015上实例化Foo,如下所示:

Foo<double, int> f;
f();

Surprisingly, f() prints "Foo_0", which means the partial specialized template Foo_1 isn't chosen. 令人惊讶的是,f()打印“Foo_0”,这意味着未选择部分专用模板Foo_1。 What's even stranger, when I comment the specialization of Foo::bar(double), f() prints "Foo_1"! 甚至更奇怪的是,当我评论Foo :: bar(double)的特化时,f()打印“Foo_1”!

Then I test this: 然后我测试一下:

Foo<int, int> f;
f();

This time, f() also prints "Foo_1", the class specialization is applied. 这次,f()也打印“Foo_1”,应用了类专业化。

So it seems that the specialization of member bar() do influence the application of partial specialization of the class template. 所以成员bar()的特化似乎影响了类模板的部分特化的应用。 Is that true? 真的吗? Why does it work like this? 它为什么这样工作?

The explicit specialization of Foo<double, int>::bar Foo<double, int>::bar的显式特化

template<>
template<>
void Foo<double, int>::bar(double) {
    std::cout << "Now I'm specialized!\n";
}

causes an implicit instantiation of Foo<double, int> . 导致Foo<double, int>的隐式实例化。 This is a better match than the partially specialized Foo<T, int> , so you get Foo_0 instead of Foo_1 , unless you comment out the specialization of bar . 这是比部分专用的Foo<T, int>更好的匹配,所以你得到Foo_0而不是Foo_1 ,除非你注释掉bar

What you could do is to move bar(double) into the general class template Foo<T, S> as a regular overloaded member function 你可以做的是将bar(double)移动到通用类模板Foo<T, S>作为常规重载成员函数

template<class T, class S>
class Foo {
    // as before

    void bar(double) {
        std::cout << "Now I'm overloaded!\n";
    }
};

Now you will get Foo_1 , live example . 现在你将获得Foo_1现场示例 Note that you won't be able to call Foo<double, int>::bar(double) anymore. 请注意,您将无法再调用Foo<double, int>::bar(double) If you want that, then you need to add a bar member to the partial specialization Foo<T, int> as well. 如果你想要,那么你需要在部分特化Foo<T, int>添加一个bar成员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM