【问题标题】:Incorrect template function being called from within a templated class virtual function从模板化的类虚函数中调用了不正确的模板函数
【发布时间】:2018-07-01 06:07:40
【问题描述】:

我正在尝试从类的重写虚函数中调用模板化函数。不幸的是,我似乎只能调用默认实现。

#include <iostream>
#include <string>
#include <typeinfo>
#include <memory>

template<typename T1,
         typename T2>
class B;

template<typename T1,
         typename T2>
void bar(B<T1, T2> &b)
{
    std::cout << "T1 = " << typeid(T1).name() << std::endl;
    std::cout << "T2 = " << typeid(T2).name() << std::endl;
    std::cout << "Default template" << std::endl;    
}

template<typename T2>
void bar(B<int, T2> &b)
{
    std::cout << "Specialized template" << std::endl;    
}

template<typename T1, typename T2>
void foobar(T1 t1, T2 t2)
{
    std::cout << "Default template [foobar]" << std::endl;
}

template<typename T2>
void foobar(int t1, T2 t2)
{
    std::cout << "Specialized template [foobar]" << std::endl;
}

class A 
{
public:
    A() {}
    ~A() {}

    virtual void foo() = 0;
};

template<typename T1,
         typename T2>
class B : public A 
{
public:
    B() {}
    ~B() {}

    void foo() override
    {
        std::cout << "T1 = " << typeid(T1).name() << std::endl;
        std::cout << "T2 = " << typeid(T2).name() << std::endl;
        bar<T1, T2>(*this);
    }
};

int main()
{
    auto a = new B<int, char>();
    a->foo();

    bar<int, char>(*a);

    int i = 0;
    char b = 'b';
    foobar(i, b);
    foobar(b, b);

    return 0;
}

输出是(见:here

T1 = i
T2 = c
T1 = i
T2 = c
Default template
T1 = i
T2 = c
Default template
Specialized template [foobar]
Default template [foobar]

很明显,重写的 foobar 函数可以正常工作,但是,对于 bar 函数,永远不会调用专用版本。控制台的输出显示第一个模板参数显然是一个 int,因此应该调用覆盖的 bar 函数。

我感觉这与虚函数foo 与类模板[1] 不兼容有关。原则上,我想生成不同版本的 B 类,它们将覆盖虚拟 foo 函数并调用 bar 的适当特化(取决于类模板参数)。

我知道我可以只对 B 类进行部分专业化,但这会导致我的设计出现大量重复代码和其他复杂情况。 (我也知道其中一些可以通过模板继承来缓解)。

我主要是好奇为什么不调用正确版本的bar,尽管模板参数显然是正确的。我想知道为什么会发生冲突,而不仅仅是对完全重新设计的建议。

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    这里的问题是bar 实际上是两个独立的模板函数重载,首先具有优先级。要为函数模板定义部分特化,您可以使用代理模板类的技巧来完成所有工作:

    template<typename T1, typename T2> class
    bar_impl
    {
        public: static void
        Do(B<T1, T2> &b)
        {
            std::cout << "T1 = " << typeid(T1).name() << std::endl;
            std::cout << "T2 = " << typeid(T2).name() << std::endl;
            std::cout << "Default template" << std::endl;    
        }
    };
    
    template<typename T2> class
    bar_impl<int, T2>
    {
        public: static void
        Do(B<int, T2> &b)
        {
            std::cout << "Specialized template" << std::endl;   
        }
    };
    
    template<typename T1, typename T2> void
    bar(B<T1, T2> &b)
    {
        return bar_impl<T1, T2>::Do(b);
    }
    

    online compiler

    【讨论】:

    • 这正是我正在寻找的。我应该能够在 bar_impl 类中添加多个专用函数,这很棒。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 2012-11-04
    • 2014-02-06
    • 2010-11-19
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多