C++ - 模板类中模板函数的单独声明/定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13351474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:13:25  来源:igfitidea点击:

C++ - Separate declaration/definition for template function in template class

c++ooptemplatesmethodsimplementation

提问by Brandon Miller

I am aware that the syntax for declaring a template class method in a header and defining it in a source file goes as so:

我知道在头文件中声明模板类方法并在源文件中定义它的语法如下:

myclass.h

我的类.h

template <typename T>
class MyClass {
  public:
    void method(T input);
  private:
    T privVar;
};

myclass.cpp

我的类.cpp

template <typename T>
void MyClass<T>::method(T input) {
    privVar = input;
}

But, what if the method is also a template? I have am adding methods to the basic_stringclass, and I want to know how to write the implementation for the functions.

但是,如果该方法也是模板呢?我正在向basic_string类添加方法,我想知道如何编写函数的实现。

MyString.h

我的字符串

template <class _Elem   = TCHAR,
          class _Traits = std::char_traits<_Elem>,
          class _Ax     = std::allocator<_Elem>>
class String
    : public std::basic_string<_Elem, _Traits, _Ax> {
  private:
    // Types for the conversion operators.
    typedef       _Elem* _StrTy;
    typedef const _Elem* _ConstStrTy;

    //...

  public:
        // Conversion operators so 'String' can easily be
        // assigned to a C-String without calling 'c_str()'.
    operator _StrTy() const {
        return const_cast<_StrTy>(this->c_str());
    }

    operator _ConstStrTy() const {
        return this->c_str();
    }

    // ... Constructors ...

    /*------------ Additional Methods ------------*/

    //! Converts a value of the given type to a string.
    template <class _ValTy> static String ConvertFrom(_ValTy val);

    //! Converts a string to the given type.
    template <class _ValTy> static _ValTy ConvertTo(const String& str);
    template <class _ValTy> _ValTy ConvertTo(void) const;

    //! Checks if a string is empty or is whitespace.
    static bool IsNullOrSpace(const String& str);
    bool IsNullOrSpace(void) const;

    //! Converts a string to all upper-case.
    static String ToUpper(String str);
    void ToUpper(void);

    // ...
};

How could I implement template <class _ValTy> static String ConvertFrom(_ValTy val);? Because now not only do I need to specify the class template, but the function template too. I am betting the code I'm about to write isn't valid, but it should show what I am trying to accomplish:

我该如何实施template <class _ValTy> static String ConvertFrom(_ValTy val);?因为现在我不仅需要指定类模板,还需要指定函数模板。我打赌我即将编写的代码无效,但它应该显示我正在尝试完成的任务:

MyString.cpp

我的字符串文件

template <class _Elem, class _Traits, class _Ax>
template <class _ValTy>
String<_Elem, _Traits, _Ax> String<_Elem, _Traits, _Ax>::ConvertFrom(_ValTy val) {
    // Convert value to String and return it...
}

I am not advanced at all with templates. Not only am I very doubtful that the above is valid, it seems cumbersome to write and not very readable. How would I go about implementing the template methods, and the static template methods which returns its own class type? Because I don't want to define them in the header.

我对模板一点都不先进。不仅我非常怀疑上面的说法是否成立,而且写起来似乎很麻烦,可读性也不是很好。我将如何实现模板方法,以及返回自己的类类型的静态模板方法?因为我不想在标题中定义它们。

回答by Rost

Syntax of definition of template member functions outside of template is like this:

模板外的模板成员函数定义语法如下:

template <class T> struct A
{
   template <class X> void f();
};

template<class T> template<class X> void A<T>::f()
{
}

So your code is correct.

所以你的代码是正确的。

Would like to note that defining template members in .cppis not very useful. In this case you shall explicitly instantiate them with all types you need to use with this template. Or do not use them outside this .cppwhich doesn't make sense.

需要注意的是,在中定义模板成员.cpp并不是很有用。在这种情况下,您应使用需要与此模板一起使用的所有类型显式实例化它们。或者不要在没有意义的情况下使用它们.cpp

回答by Mark B

Before I answer your question, let me first say: Don't do this. Extend std::stringby using free-functions instead, much like the standard library implements many algorithms. Additionally I'd suggest doing it for ranges rather than strings only but that's more subjective.

在我回答你的问题之前,让我先说:不要这样做。std::string使用自由函数进行扩展,就像标准库实现了许多算法一样。此外,我建议针对范围而不是string仅针对s执行此操作,但这更主观。

Also note that std::stringavoids implicit conversions to C-strings not to make your life harder, but to protect your code from a wide variety of obscure bugs that can be caused by unexpected implicit conversions. I would think very long and hard about implementing them. Just think about this: It takes you a few extra moments to type.c_str()once when you write the code, and for the rest of eternity anyone who reads your code will immediately know that it's being used as a C-style string and not as a std::string.

另请注意,std::string避免隐式转换为 C 字符串并不是为了让您的生活更艰难,而是为了保护您的代码免受可能由意外隐式转换引起的各种模糊错误的影响。我会认真考虑实施它们。想一想:.c_str()在编写代码时输入一次需要额外的时间,而在接下来的时间里,任何阅读您代码的人都会立即知道它被用作 C 风格的字符串,而不是用作std::string.

To answer your question, just put the code in the header:

要回答您的问题,只需将代码放在标题中:

//! Converts a value of the given type to a string.
template <class _ValTy> static String ConvertFrom(_ValTy val)
{
    // Code here
}

Finally note that identifiers starting with underscore+capital letter (and many other things starting with _) are reserved for the compiler and thus all bets are off as to your program's functionality.

最后请注意,以下划线+大写字母开头的标识符(以及许多其他以 开头的标识符_)是为编译器保留的,因此所有的赌注都与您的程序功能有关。

回答by Josh Heitzman

Your function definition is valid, and it can't be defined outside of the class declaration in a less verbose way. Since you want to put the function definition in a .cpp file you can't take advantage of combining the function definition with the more concise function declaration. By putting the function definition in a .cpp file you will also have to explicitly instantiate all needed specializations of your template class.

您的函数定义是有效的,并且不能以不那么冗长的方式在类声明之外定义。由于您想将函数定义放在 .cpp 文件中,因此无法利用将函数定义与更简洁的函数声明相结合的优势。通过将函数定义放在 .cpp 文件中,您还必须显式实例化模板类的所有需要​​的特化。