C ++中的一些基本模板问题

时间:2014-01-11 15:23:40

标签: c++ templates

在使用模板编写C ++时遇到3个问题。似乎VS2013可以编译下面的代码。

代码在这里:

// template_test.h

#include <iostream>
using namespace std;

template<class T>
class mytest
{
public:
    void method(T input);
    void common();
};

template <>
class mytest<char>
{
public:
    void method(char input);
    void common();
};


template<class T>
void mytest<T>::method(T input)
{
    cout << input << endl;
}


template<class T>
void mytest<T>::common()
{
    cout << "common" << endl;
}

// template_test.cpp

#include "template_test.h"

void mytest<char>::method(char input)
{
    cout << "char:" << input << endl;
}

void mytest<char>::common()
{
    cout << "common" << endl;
}

// main.cpp中

#include "template_test.h"
using namespace std;

int main()
{

    mytest<char> test_char;
    test_char.method('1');
    test_char.common();

    mytest<int> test_int;
    test_int.method(1);
    test_int.common();

    system("pause");

    return 0;
}

1.在mytest :: method

的实现中
template<class T>
void mytest<T>::method(T input)
{
    cout << input << endl;
}

我可以删除第二个T表达式吗?我在VS2013中尝试使用以下代码而不是原始cpp,并且无法编译。

template<class T>
void mytest::method(T input)
{
    cout << input << endl;
}

看起来很奇怪,我需要以如此多的模板参数的复杂形式使用它。

2.在.h文件中,我宣布了课程&#39; mytest&#39;使用模板专业化

template <>
class mytest<char>
{
public:
    void method(char input);
    void common();
};

并且每个函数的实现都在

// template_test.cpp

#include "template_test.h"


void mytest<char>::method(char input)
{
    cout << "char:" << input << endl;
}

void mytest<char>::common()
{
    cout << "common" << endl;
}

我的问题是,当我将.hpp文件中的实现与非专业化模板类的实现一起放在.h文件中时,VS2013也会报告错误代码。

我知道非专业化模板类的声明和实现应该在同一个头文件中,因为c ++不应该允许在其他文件中展示非专业化模板类。但为什么专门化模板类的声明和实现应该在不同的代码文件中呢?

3.在头文件中

template<class T>
class mytest
{
public:
    void method(T input);
    void common();
};

template <>
class mytest<char>
{
public:
    void method(char input);
    void common();
};

很明显,这个功能常见于&#39;是专业化和非专业化模板类的常见部分。但是,专业化将专注于全班。我只想保留常用功能,因此不需要在专业化版本中编写相同的功能。我不知道该怎么做。

我是使用c ++模板编程领域的新手,上面的3个问题基本且简单。我在谷歌搜索一些问题,但仍然不知道。所以我在这里发布我的问题。

2 个答案:

答案 0 :(得分:2)

  1. <T>可以省略template <typename T> void mytest<T>::method(T input)吗?

    没有。虽然在简单的情况下似乎是多余的,但在更复杂的情况下,例如,当存在多个部分特化时,它变得必要。保持语法一致也很有帮助。

  2. 当将完全专用的类模板的成员函数的定义放入标题时,会出现“错误”(我假设你得到多个声明的符号)。

    完全专用的类模板的成员函数被视为非类模板的成员函数:只有一个版本,编译器永远不需要隐式实例化它。因此,函数隐式内联,就像任何函数模板的情况一样,并且可能需要由编译器实例化。如果要将定义放入标题中,则需要将其明确声明为inline

  3. 如何在类模板及其专业化之间共享函数?

    除了语法之外,类模板及其任何特化都没有任何共同之处。他们是完全独立的阶级。有两种方法可以在不同的专业化之间共享通用功能:

    1. 将通用功能放入公共基类并在那里实现逻辑。如果功能需要访问实际模板的成员,则可以使用curiously recurring template pattern授予基类访问专业化的权限。
    2. 不要将公共功能作为成员函数,而是使其成为接受任何特化的函数模板。
    3. 根据您的常用功能需要做什么,一种或另一种方法效果更好。

答案 1 :(得分:1)

DietmarKühl对1的回答的一小部分补充:感受差异:

  • 实现非专业化类模板template <class T> class mytest

    的方法
    template <class T>
    void mytest<T>::method(T input)
    {
        // ...
        // use of input
    }
    
  • 为对象指针实现部分类模板特化template <class T> class mytest<T*>的方法:

    template <class T>
    void mytest<T*>::method(T* input)
    {
        // ...
        // use of *input
    }
    
  • 为指向另一个类数据成员的指针实现部分类模板特化template <class U, class V> class mytest<U V::*>的方法:

    template <class U, class V>
    void mytest<U V::*>::method(V& object, U V::* input)
    {
        // ...
        // use of object.*input
    }
    
  • 实现完整类模板专业化template <> class mytest<char>的方法:

    void mytest<char>::method(char input)
    {
        // ...
        // use of input
    }
    
  • 实现非专业化类模板template <class T> class mytest<T>的完全专业化方法:

    template <>
    void mytest<int>::method(int input)
    {
        // ...
        // use of input
    }