简体   繁体   English

C ++铸造模板类

[英]C++ casting of templated class

I have a question about templates. 我有关于模板的问题。 I would like to have a templated class that contains, say, an array of either float's or double's. 我想有一个模板化的类,其中包含一个float或double的数组。

I can write a clone() function that duplicates it. 我可以编写一个复制它的clone()函数。 No problem. 没问题。 However, I would like to have another function called cast() that does a translation back and forth between double and float. 但是,我想有另一个名为cast()的函数,它在double和float之间来回转换。 This has been somewhat discussed before but I don't think the problem is the same: 这在以前有过讨论,但我不认为问题是一样的:

stackoverflow.com/questions/714213/c-template-casting stackoverflow.com/questions/714213/c-template-casting

The problem I have is a compiler error, not a linker error. 我遇到的问题是编译器错误,而不是链接器错误。 The error message is: 错误消息是:

main.cpp: In function `void caster()':
main.cpp:63: error: expected primary-expression before "double"
main.cpp:63: error: expected `;' before "double"
main.cpp:64: error: expected primary-expression before "float"
main.cpp:64: error: expected `;' before "float"
main.cpp:65: error: expected primary-expression before '>' token
main.cpp:65: error: expected primary-expression before ')' token

I dumped the code below. 我抛弃了下面的代码。 The lines 63, 64, and 65 are where I commented with "Error here". 第63,64和65行是我在这里评论“Error here”的地方。

By the way, my compiler is "GNU C++ version 3.4.5 20051201 (Red Hat 3.4.5-2) (x86_64-redhat-linux) compiled by GNU C version 3.4.5 20051201 (Red Hat 3.4.5-2)". 顺便说一句,我的编译器是GNU C版本3.4.5 20051201(Red Hat 3.4.5-2)编译的“GNU C ++版本3.4.5 20051201(Red Hat 3.4.5-2)(x86_64-redhat-linux)” 。

After some Googling, it turns out that someone has already experienced this problem: 经过一些谷歌搜索后,事实证明有人已经遇到过这个问题:

gcc.gnu.org/ml/gcc-help/2006-04/msg00022.html gcc.gnu.org/ml/gcc-help/2006-04/msg00022.html

There is a solution here: 这里有一个解决方案:

gcc.gnu.org/ml/gcc-help/2006-04/msg00023.html gcc.gnu.org/ml/gcc-help/2006-04/msg00023.html

But when the original poster asks as to why it works, the answer is not very clear: 但是当原始海报询问它为何起作用时,答案并不十分明确:

gcc.gnu.org/ml/gcc-help/2006-04/msg00025.html gcc.gnu.org/ml/gcc-help/2006-04/msg00025.html

Unfortunately, the link is dead, and I don't own the third edition of Stroustrup. 不幸的是,链接已经死了,我没有第三版Stroustrup。 Now, I have my fix, my code works. 现在,我有我的修复,我的代码工作。 But, Stackoverflow, why does it work? 但是,Stackoverflow,它为什么有效?


#include <stdio.h>

// =================== This would be the header ===================
template <class T>
class foo
{
public:
             foo(const T val) {d_data = new double; *d_data = val;}
    virtual ~foo() {delete d_data;};

    foo* clone() const;

    template<class U>
    foo<U>* cast() const;

private:
    double *d_data;
};

// =================== This would be the implementation of the class ===================
template<class T>
foo<T>* foo<T>::clone() const
{
    return new foo<T>(*d_data);
}

template<class T>
template<class U>
foo<U>* foo<T>::cast() const
{
    return new foo<U>(*d_data);
}

template class foo<float>;
template class foo<double>;

template foo<float>* foo<float>::cast() const;
template foo<float>* foo<double>::cast() const;
template foo<double>* foo<float>::cast() const;
template foo<double>* foo<double>::cast() const;

// =================== Using the class ===================
template <class T>
void caster()
{
    foo<double> *f1 = NULL;
    foo<float>  *f2 = NULL;
    foo<T>      *f3 = NULL;

    // I am looking at something that compiles
    // I don't care about linking for now
    // This will crash at runtime because of
    // NULL, but that's just an example

    f1->cast<double>(); // compiler OK
    f1->cast<float>();  // compiler OK
    f1->cast<T>();      // compiler OK

    f2->cast<double>(); // compiler OK
    f2->cast<float>();  // compiler OK
    f2->cast<T>();      // compiler OK

    f3->cast<double>(); // Error here
    f3->cast<float>();  // Error here
    f3->cast<T>();      // Error here

    f3->foo<T>::template cast<double>(); // It works!
    f3->foo<T>::template cast<float>();  // It works!
    f3->foo<T>::template cast<T>();      // It works!
}

int main(int argc, char **argv)
{
    return 0;
}
f3->cast<double>(); // Error here 

In this line, the compiler does not know if the < after f3->cast is supposed to mean the beginning of template arguments or if it is a less than comparison operator. 在这一行中,编译器不知道< after f3->cast是否应该表示模板参数的开头,或者它是否小于比较运算符。

To explicitly specify that it stands for beginning of template argument. 要明确指定它代表模板参数的开头。 The correct way is 正确的方法是

f3->template cast<double>();

In summary, The .template notation (and similar notations such as ->template ) should be used only inside templates and only if they follow something that depends on a template parameter (such as the expression f3 which depends upon the template parameter T ) 总之, .template表示法(以及类似符号,如->template )只能在模板内部使用,并且只有在它们遵循依赖于模板参数的内容时才会使用(例如依赖于模板参数T的表达式f3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM