用不完整的参数转发模板的声明

时间:2018-01-19 23:43:04

标签: c++ c++11 templates

我坚持使用此代码并且不理解错误。 我尝试在标头中进行模板特化的前向声明,然后在源文件中定义此特化。当我尝试包含此标题时,编译器会抱怨我使用的是不完整类型。

错误: $ error: invalid use of incomplete type 'A_Template<Stub *>' std::cout << A_Template<Stub*>().int_method() << std::endl; ^~~~~~~~~~~~~~~~~~~ $ note: forward declaration of 'A_Template<Stub *>' struct A_Template<Stub*>; ^

/* a.h */
#pragma once
template <class T>
struct A_Template{};

class Stub{};

template<>
struct A_Template<Stub*>;


/* a.cpp */
#include "a.h"

template<>
struct A_Template<Stub*> {
    int int_method() {return 42;}
};


/* main.cpp */
#include <iostream>
#include "a.h"

int main() {    
    std::cout << A_Template<Stub*>().int_method();
    return 0;
}

谁能告诉我什么是错的,有没有办法解决它?

1 个答案:

答案 0 :(得分:4)

这是完全相同的问题,你试图将任何类/结构的定义放在源文件中,与模板的东西无关。类的类型在以前没有在同一个翻译单元中看到它的定义时是不完整的,并且除了传递指针和对该类型的引用之外,不能以任何方式使用不完整的类类型。

因此#include "a.h"引入了A_Template<Stub*>的声明,但没有定义,因此使用它的表达式是非法的。基本上,在没有看到定义的情况下,编译器无法知道:

  • 该类型的A_Template<Stub*>对象需要多少存储空间
  • 默认构造函数调用A_Template<Stub*>()是否有效,
  • 如果它是有效的,构造函数的签名(可能是没有参数的普通构造函数,带有一些默认参数的构造函数或模板构造函数),
  • .int_method成员访问是否有效,
  • 如果有效,int_method是否命名成员函数或命名可能是函数指针的对象或具有operator()的类类型,
  • 如果int_method是成员函数,则是成员函数的签名,就像构造函数一样,或者
  • 对临时A_Template<Stub*>的隐式析构函数调用是否有效。

类模板显式或部分特化的定义通常需要在头文件中,就像任何其他类定义一样。但是可以向前声明它并在必要时稍后定义它。