C ++模板化函数和前向声明 [英] C++ templated function and forward declarations

查看:69
本文介绍了C ++模板化函数和前向声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一些使用MSVC在Windows上编译和链接(甚至发布了商业产品)的代码.虽然它无法在GCC中编译,但出现以下错误:

I'm working on some code that compiles and links (and even has released commercial products) on Windows using MSVC. It doesn't compile with GCC though, I get the following errors:

.../CBaseValue.h: In member function 'bool CBaseValue::InstanceOf()':
.../CBaseValue.h:90:18: error: invalid use of incomplete type 'struct CValueType'
.../CBaseValue.h:11:7: error: forward declaration of 'struct CValueType'

CBaseValue.h

class CValueType;

class CBaseValue {
public:

...

    template <typename _Type>
    bool InstanceOf() {
        CValueType* pType = GetType();
        if(pType == NULL) {
            return false;
        }
        else {
            return pType->IsDerivedFrom<_Type>();
        }
    }

...

}

CValueType.h

class CValueType : public CBaseValue  {
public:

...

    template <typename _Type>
    bool IsDerivedFrom() {
        return IsDerivedFrom(_Type::TYPEDATA);
    }

...

}

我理解为什么这是一个问题.基类(CBaseValue)具有使用派生类(在本例中为CValueType)的模板化函数.

I understand why this is a problem. The base class (CBaseValue) has a templated function that uses a derived class (in this case CValueType).

MSVC似乎并没有完全遵循C ++规范,而我只是被它咬了.但是,现在也更希望使用前向声明,直到实际编译调用模板化函数的代码为止的MSVC行为.有谁知道一种解决方法,可以在不重写大量基本代码的情况下使此代码与GCC一起使用?

It looks like MSVC isn't exactly obeying the C++ spec here and I've just been bitten by it. But the MSVC behavior of using the forward declaration until code calling the templated function is actually compiled is also more desirable right now. Does anybody know of a work-around where I can get this code working with GCC without having to rewrite a lot of base code?

从我自己的研究看来,将'-fno-implicit-templates'传递给g ++可能会有所帮助,但随后我需要显式定义被调用的模板类型.它们很多,所以如果我能避免的话,我会更喜欢它.如果大家普遍认为这是我最好的选择……那就去吧!

From my own research it looks like passing '-fno-implicit-templates' to g++ would help but then I'd need to explicitly define the called template types. There are a lot of them so if I can avoid that I'd prefer it. If the general consensus is that this is my best option... so be it!

万一有人想知道,我正在将代码移植到Mac上,这就是为什么我们现在使用GCC的原因.

And in case anybody is wondering, I'm porting the code over to the Mac which is why we're now using GCC.

推荐答案

这是标准的格式错误,但不需要诊断.MSVC可以很好地诊断这种特殊情况(即使实例化发生!).

This is ill-formed by the Standard, but no diagnostic is required. MSVC is fine not diagnosing this particular case (even when instantiation happens!).

更具体地说,(C ++ 03)标准规则为14.6/7

More specifically, the (C++03) Standard rules at 14.6/7

如果在非依赖名称中使用的类型在定义模板时是不完整的,但在完成实例化时是完整的,并且该类型的完整性影响程序是否格式正确或影响程序语义的程序格式不正确;无需诊断.

If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required.

因此解决方案是仅使类型依赖,但安排它在实例化期间指定该类型.例如,您可以通过这样重写模板来做到这一点

So the solution is to just make the type dependent, but arrange it that during instantiation, that type is designated. For example, you can do that by rewriting your template like this

template<typename T, typename> // just ignore second param!
struct make_dependent { typedef T type; };

template <typename Type> // eww, don't use "_Type" in user code
bool InstanceOf() {
    typename make_dependent<CValueType, Type>::type* pType = GetType();
    // ...
        return pType->template IsDerivedFrom<Type>();
    // ...
}

这篇关于C ++模板化函数和前向声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆