【问题标题】:How to define a template method for a non-template class?如何为非模板类​​定义模板方法?
【发布时间】:2011-06-11 01:36:36
【问题描述】:

我的编译器对我实现模板方法的方式不满意。它为这些实现提供了 的错误消息,例如“未定义的类型 T”。

这是我的第一个方法,它是在类块之外实现的:

class VectorConvertor
{
    public:
        // ...
        template <class T>
        static void ReverseVectorElements(std::vector<T> & Vector);
        // ...
};

template <class T>
void VectorConvertor::ReverseVectorElements(std::vector<T> & Vector)
{
    std::vector<T>::size_type size = Vector.size();
    T swap;
    for (std::vector<T>::size_type i=0; i<size/2; i++)
    {
        swap = Vector.at(i);
        Vector.at(i) = Vector.at(size-1-i);
        Vector.at(size-1-i) = swap;
    }
}

另一个是这个;这次方法是在类内部实现的:

class ElementaryMath
{
    public:
        // ...
        template <class T> static char sign(T num)
        {
            return (num >= static_cast<T>(0)) ? static_cast<char>(+1) : static_cast<char>(-1);
        }
        // ...
}

我的代码有什么问题,还是只是编译器本身的问题?

IDE 和编译器:Visual Studio 2010

【问题讨论】:

    标签: c++ visual-studio templates methods implementation


    【解决方案1】:

    您的代码在 VS2005 上编译没有错误(除了 ElementaryMath 定义末尾缺少分号),因此您可能正在查看编译器错误。

    VS2010 SP1 提供测试版here。可能会有所帮助,但显然它的测试版...

    【讨论】:

    • 提到'typename'的答案是在谈论依赖类型,而不是模板参数列表。
    • 完全不正确的答案,但我今天已经完成了投票。
    • @FredNurk 谢谢,我没有意识到这一点。我已经删除了关于 typename 的误导性部分。
    【解决方案2】:
    class VectorConvertor
    {
        public:
        // ...
        template <typename T>
        static void ReverseVectorElements(std::vector<T> & Vector);
    };
    
    template <typename T>
    void VectorConvertor::ReverseVectorElements(std::vector<T> & Vector)
    {
        std::vector<T>::size_type size = Vector.size();
        T swap;
        for (std::vector<T>::size_type i=0; i<size/2; i++)
        {
            swap = Vector.at(i);
            Vector.at(i) = Vector.at(size-1-i);
            Vector.at(size-1-i) = swap;
        }
    }
    
    int main()
    {
        std::vector <int> i(10,0);
    
        VectorConvertor obj;   // Since your class isn't a template, template parameter
                               // isn't required for a class template instantiation.
                               // However, if your class was a template class, template-
                               // parameter must have been required for a class template
                               // instantiation.
    
        obj.ReverseVectorElements(i);  // Equal to obj.ReverseVectorElements<int>(i);
                                       // Based on type of i, compiler can instantiate a 
                                       // template function by default.
        getchar();
        return 0;
    }
    

    希望这会有所帮助!

    【讨论】:

    • try compiling这个吗? (请注意,某些版本的 msvc 的依赖名称是错误的。)
    • @Fred Nurk:你的意思是说这是编译器的问题还是我的编程方式不对?请提供有关防止自己再次出错的问题的信息:)
    • 两者;请参阅我上面给出的链接codepad.org/QQOi7sCT,并阅读相关名称(在此处和其他地方的其他答案中)。
    【解决方案3】:

    您的代码在我看来没问题。但有一件事在我脑海中浮现。你能检查一下之前是否定义了函数“sign”吗?只需将鼠标悬停在其上即可。 C 运行时库使用“#define”关键字实现它的一些函数,因此您不能在之后定义具有相同名称的函数。

    【讨论】:

    • @hkBattousai:winapi 中的 max 和 min 宏总是让人头疼。有一个特殊的配置宏要定义(最好在项目设置中做)以防止 winapi 创建它们;例如,参见connect.microsoft.com/VisualStudio/feedback/details/101300/…。 (在您删除评论之前更有意义,但我将其留在这里,因为我认为它仍然适用。)
    • 哦,你说的对,真的。不是函数“sign()”,而是另一个函数(第一个编译器错误),“max()”的定义方式与您所说的相同。我将其取消定义如下,现在没有编译器错误。 >>#ifdef max --- #undef max --- #end
    【解决方案4】:

    此处输入名称:

    template <class T>
    void VectorConvertor::ReverseVectorElements(std::vector<T> & Vector)
    {
        typename std::vector<T>::size_type size = Vector.size();
        T swap;
        for (typename std::vector<T>::size_type i=0; i<size/2; i++)
        {
            swap = Vector.at(i);
            Vector.at(i) = Vector.at(size-1-i);
            Vector.at(size-1-i) = swap;
        }
    }
    

    【讨论】:

      【解决方案5】:

      您缺少一些typenames 和分号,但除此之外,代码似乎还可以。恕我直言,如果它仍然不起作用,是时候提交错误了。

      顺便说一句,交换代码最好使用std::swap

      【讨论】:

      • 除了使用 std::swap (将用作 {using std::swap; swap(a, b);})整个循环可以替换为 std::swap_ranges( Vector.begin(), Vector.begin()+Vector.size()/2, Vector.rbegin())
      • @Grizzly 好吧,如果他只想反转,他可以 std::reverse
      • @CashCow:iter_swap 起源于准标准 C++,现在没有理由使用它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多