【问题标题】:Specialising a templated function for a templated (Armadillo) class为模板化(犰狳)类专门化模板化函数
【发布时间】:2014-10-01 22:11:12
【问题描述】:

我正在尝试组合一个非常简单的日志记录类,它专门处理某些类型,尤其是向量。我希望在使用 << 运算符时具有默认行为,但在某些情况下修改它。设置是:

class LoggerStream
{
    template <typename ArgType>
    LoggerStream & operator<< (const ArgType &arg)
    {
        // Standard logging logic
        return *this;
    }

    template <typename DataType>
    LoggerStream & operator<< (const std::vector<DataType> &arg)
    {
        // Specialised logging logic
        return *this;
    }

    template <typename DataType>
    LoggerStream & operator<< (const arma::Col<DataType> &arg)
    {
        // Specialised logging logic
        return *this;
    }

    LoggerStream & operator<< (const double &arg)
    {
        // Specialised logging logic
        return *this;
    }

    // Other stuff...
};

double 案例工作正常。问题是对于向量类型的子类,通用模板似乎具有优先权,而更具体的模板被忽略了。

由于所有三个模板案例只有一个通用模板参数,我猜向量案例不被认为是最专业的,但如果它被认为是模棱两可的,我预计会出现编译器错误。 (它编译得很好。)那么我怎样才能指出一个特化但仍然概括矢量元素的类型呢?提前致谢。

我想这与Col 类是如何实现的一些细节有关。我也在使用(和别名)arma::Col&lt;T&gt;::fixed&lt;N&gt;,但是为此编写一个特定的重载似乎没有帮助。欢迎任何想法。

【问题讨论】:

  • Cannot reproduce。您需要向我们展示一个完整的可编译示例来重现您的问题。
  • 无法重现。尝试猜测,您的向量是std::vector&lt;T&gt; 而不是std::vector&lt;T, special_alloc&lt;T&gt; &gt;
  • 需要明确的是,矢量版本也是重载,而不是专业化。
  • 嗯。这里没有特殊的分配器,据我所知没有什么不寻常的。我会进一步调查并跟进。感谢您对其进行测试。
  • 好吧,抱歉。我没有意识到我所有的例子实际上都是arma::Col 而不是std::vector,所以特别是这种情况是有问题的。我想这使得这是一个犰狳特有的问题。我会编辑以反映这一点。同时,感谢您帮助澄清问题不是我的普遍误解!

标签: c++ templates overloading armadillo


【解决方案1】:

我回答我自己的问题不是因为我(还)有一个解决方案,而是为了在进一步调查后澄清问题。事实上,这似乎并不特定于arma::Col;相反,当参数是子类类型时,问题似乎在于更具体的重载的优先级。一个不使用犰狳就说明问题的简单例子是

#include <iostream>
#include <vector>

using namespace std;

template <typename DataType>
class MyVector : public std::vector<DataType> {};

class LoggerStream
{
public:
    template <typename ArgType>
    LoggerStream &operator<< (const ArgType &arg)
    {
        cout << "In general" << endl;
        return *this;
    }

    template <typename DataType>
    LoggerStream &operator<< (const std::vector<DataType> &arg)
    {
        cout << "In vector" << endl;
        return *this;
    }
};

int main()
{
    LoggerStream foo;
    std::vector<float> v;
    foo << v;  // Prints "In vector", as expected
    MyVector<float> w;
    foo << w;  // Prints "In general" (but only if the general case exists)
}

因此,使用子类MyVector 会调用通用函数,而不是专用函数。但是,如果第一个版本被注释掉,那么两个调用都会产生“在向量中”。所以出于某种原因,两者都被认为是合适的,但一般功能是首选。

我仍然不知道的是如何在不为单个子类案例明确写出大量特定重载的情况下阻止这种情况发生...

【讨论】:

    【解决方案2】:

    我无法复制它。此代码按预期工作:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class LoggerStream
    {
    public:
        template <typename ArgType>
        LoggerStream &operator<< (const ArgType &arg)
        {
            // Standard logging logic
            cout << "In general" << endl;
            return *this;
        }
    
        template <typename DataType>
        LoggerStream &operator<< (const std::vector<DataType> &arg)
        {
            // Specialised logging logic
            cout << "In vector" << endl;
    
            return *this;
        }
    
    };
    
    int main()
    {
        LoggerStream foo;
        vector<int> v;
        foo << v; // calling the vector specialization
    }
    

    【讨论】:

    • 感谢您的检查。这似乎确实是特定于arma::Col
    猜你喜欢
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多