【问题标题】:something confusing about class template partial specialization & class member specialization关于类模板部分专业化和类成员专业化的一些混淆
【发布时间】:2017-02-14 10:51:59
【问题描述】:

这里我定义了一个类模板 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";
    }
};

我像这样在 VS2015 上实例化 Foo:

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

令人惊讶的是,f() 打印出“Foo_0”,这意味着未选择部分专用模板 Foo_1。 更奇怪的是,当我评论 Foo::bar(double) 的特化时,f() 会打印“Foo_1”!

然后我测试一下:

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

这一次,f() 也打印“Foo_1”,应用了类特化。

因此,成员 bar() 的特化似乎确实影响了类模板的部分特化的应用。真的吗?为什么会这样?

【问题讨论】:

  • 尝试将显式函数模板特化移到部分类模板特化之下。
  • @Kerrek SB 当我移动它时,编译器抱怨“类 Foo 没有成员 Bar”,似乎 bar(double) 被视为 Foo_1 的成员。
  • gcc 成功诊断问题(与 clang 相反)Demo。 (error: partial specialization of 'class Foo&lt;T, int&gt;' after instantiation of 'class Foo&lt;double, int&gt;' [-fpermissive])
  • bar 的显式特化导致 Foo&lt;double, int&gt; 的隐式实例化,这比 Foo&lt;T, int&gt; 更好地匹配,因此您得到 Foo_0 与特化的 barFoo_1 时你把它注释掉。

标签: c++ templates partial-specialization


【解决方案1】:

Foo&lt;double, int&gt;::bar 的显式特化

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

导致Foo&lt;double, int&gt; 的隐式实例化。这比部分特化的Foo&lt;T, int&gt; 更好的匹配,所以你得到Foo_0 而不是Foo_1,除非你注释掉bar 的特化。

您可以做的是将bar(double) 移动到通用类模板Foo&lt;T, S&gt; 作为常规重载成员函数

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

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

现在您将获得Foo_1live example。请注意,您将无法再拨打Foo&lt;double, int&gt;::bar(double)。如果你想要这样,那么你还需要将一个 bar 成员添加到部分专业化 Foo&lt;T, int&gt; 中。

【讨论】:

  • 谢谢,很有帮助
猜你喜欢
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多