为什么编译器似乎忽略了模板化类中的语句?

时间:2014-05-23 02:47:13

标签: c++ visual-studio

首先,代码

vector<T> kvec;

for (ulong kv = 0; kv < ke.count; kv++)
{
    T key;
    if (typeid(T) != typeid(QUAT32))
    {


        fread(&key, sizeof(T), 1, fh);
    }
    else{

        shortQuat key16;

        fread(&key16, sizeof(shortQuat), 1, fh);
        key.Parse(key16);

    }
    kvec.push_back(key);
}

key.Parse(key16);抛出以下编译器错误:

error C2039: 'Parse' : is not a member of 'libm2::VEC3F'

当然它没有;但问题是任何具有VEC3F类型的东西都不应该到达那里。显然编译器使用的第一种类型被发送到了代码片段来自哪个类,这很好 - 但为什么要忽略条件?

是的,如果我评论该行,它编译得很好 - 条件在运行时工作正常。

所以我想真正的问题是,处理这个问题的最佳方法是什么,而不必为一个专门类型复制整个类?

3 个答案:

答案 0 :(得分:2)

扩展我的评论:

if在运行时运行,而不是在编译时运行(优化器可能会删除分支,但它必须首先编译以获得那么远)。

您可以使用模板专门化, 在编译时完成(编译器为编译它之前为其提供的每种类型实例化模板化函数的单独副本 )。您可以提供专门化来强制特定类型的不同(特殊)函数体,这正是您在这种情况下所需的。

这是一个从你问题中的代码派生的例子(我假设非QUAT32s的双推回kvec是一个错字):

template<typename T>
inline void readKey(T& key, FILE* fh)
{
    fread(&key, sizeof(T), 1, fh);
}

template<>
inline void readKey<QUAT32>(QUAT32& key, FILE* fh)
{
    shortQuat key16;
    fread(&key16, sizeof(shortQuat), 1, fh);
    key.Parse(key16);
}

// ...
vector<T> kvec;
for (ulong kv = 0; kv < ke.count; kv++)
{
    T key;
    readKey(key, fh);
    kvec.push_back(key);
}

答案 1 :(得分:0)

<强>问题: 需要在模板化构造函数中处理特殊情况,需要转换为有用。但是,正如我所担心的那样,如果在编译时忽略了语句。

解决方案:

向模板添加第二种类型,并在其中一种类型中创建一个类型转换运算符。

vector<T> kvec;
for (ulong kv = 0; kv < ke.count; kv++)
{
    T2 key;
    fread(&key, sizeof(T2), 1, fh);
    kvec.push_back((T)key);
}

在大多数情况下,这个类的构造方式如下:

SomeClass c = SomeClass<typeA,typeA>(fh);
显然,在相同类型之间进行投射应该非常简单。但是在QUAT32的情况下......

SomeClass c = SomeClass<QUAT32,SHORT_QUAT>(fh);

解决方案就是这样做:

typedef struct SHORT_QUAT
{
    short x;
    short y;
    short z;
    short w;
    operator const QUAT32(){
        QUAT32 q;
        q.x = float(x < 0 ? x + 32768 : x - 32767) / 32767.0f;
        q.y = float(y < 0 ? y + 32768 : y - 32767) / 32767.0f;
        q.z = float(z < 0 ? z + 32768 : z - 32767) / 32767.0f;
        q.w = float(w < 0 ? w + 32768 : w - 32767) / 32767.0f;
        return q;
    }
}shortQuat;

然后以shortquat形式存储的数据可以转换为更有用的float格式而不会出现问题。

仅仅针对特殊情况创建整个副本似乎是浪费。我想它是两个丑陋中较小的一个。

答案 2 :(得分:0)

另一种解决方案是在模板类中声明静态变量,该变量存储先前定义的类型ID并在需要时进行检查。

id