c++ template casting

后端 未结 7 1148
伪装坚强ぢ
伪装坚强ぢ 2021-01-06 13:48

I\'m a little lost in how to cast templates. I have a function foo which takes a parameter of type ParamVector*. I would like to pass in a P

相关标签:
7条回答
  • 2021-01-06 13:58

    You mentioned "template casting" in your headline, so I'll presume that ParamVector is a templated type. That means that foo could be templated as well, and that would solve your problem.

    template <typename T>
    void foo(ParamVector<T> const& data)
    {
    }
    
    0 讨论(0)
  • 2021-01-06 14:06

    You can't do this with a direct cast because double and float are completly different sizes. Doubles are going to be 64 bits while floats are 32. A pointer forced to cast from a

    ParamVector<float>
    

    to

    ParamVector<double>
    

    is going to misinterpret the data and give you garbage. You may want to google "pointer aliasing" or just learn more about pointers in general to see how this isn't going to work.

    Think about it for a second you have one array that is a bunch of 64 bit values with fields layed out like this

    0 => abcdabcd12341234
    1 => abcdabcd12341234
    

    If you force this to be interpreted as an array of 32 bit values, its going to not be interpreted correctly. You may or may not get something like

    0 => abcdabcd
    1 => 12341234
    2 => abcdabcd
    3 => abcdabcd
    

    or it could be switched so that the 12341234's come first, or something stranger due to how the word ordering works out.

    0 讨论(0)
  • 2021-01-06 14:08

    Well, you can't. Each different actual template parameter, makes an entirely new class, which has no* relation inheritance relation with any any other class, with a diffent actual argument, made from that template.

    No relationship. Well, except that each provides the same interface, so that inside a template you can handle then the same.

    But neither the static types or the dynamic types have any relation.

    Let me drop back here, and explain.

    When I declare a pointer to classtype, like

    Foo fp*;
    

    fp has what we call a static type, of pointer-to Foo. If class Bar is a subclass of Foo, and I point fp at new Bar:

    fp = new Bar1();
    

    then we say that the object pointed to by fp has the dynamic type of Bar.

    if Bar2 also publicly derives from Foo, I can do this:

    fp = new Bar2();
    

    and without ever even knowing what fp points to, I can call virtual methods declared in Foo, and have the compiler make sure that the method defined in he dynamic type pointed to is what's called.

    For a template< typename T > struct Baz { void doSomething(); };

    Baz<int> and Baz<float> are two entirely different class types, with no relationship.

    The only "relationship" is that I can call doSomething() on both, but since the static types have no relationship, if I have a Baz<int> bi*, I can't point it to a Baz<float>. Not even with a cast. The compiler has no way to "translate" a call to the Baz doSotheing method into a call to a Baz::doSomething() method. That's because there is no "Baz method", there is no Baz, there are ony Baz<int>s and Baz<float>s, and Baz<whatevers>, but there's no common parent. Baz is not a class, Baz is a template, a set of instructions about how to make a class if and only if we have a T parameter that's bound to an actual type (or to a constant).

    Now there is one way I can treat those Bazes alike: in a template, they present the same interface, and the compiler, if it knows what kind of Baz we're really dealing with, can make a static call to that method (or a static access of a member variable).

    But a template is not code, a template is meta-code, the instructions of how to synthesize a class. A "call" in a template is not a call,it's an instruction of how to write the code to make a call.

    So. That was long winded and confusing. Outside of a template definition, there is no relationship between a ParamVector and aParamVector. So your assignment can't work.

    Well. Almost.

    Actually, with partial application of templates, you can write a template function which gives a "recipe" of how to transform a Paramvector<T> to a ParamVector<U>. Notice the T and the U. If you can write code to turn any kind of ParamVector, regardless of actual template parameter into any other kind of ParamVector, you can package that up as a partially applied template, and the compiler will add that function to, for example, ParamVector.

    That probably involves making a ParamVector<U>, and transforming each T in the ParamVector<T> into a U to put in the ParamVector<U>. Which still won't let you asign to a ParamConsumer<T>.

    So maybe you want to have both templates and inheritance. In that case, you can same that all ParamVectors regardless of type inherit from some non-template class. And then there would be a relationship between ParamVectors, they'd all be sibling subclasses of that base class.

    0 讨论(0)
  • 2021-01-06 14:11

    You can't cast templates like this because the types are unrelated.

    However, you can add a conversion function, such as:

    (Your code wasn't really complete, so I can post complete code either. Hopefully you will get the idea.)

    template<class T> class ParamVectorConsumer
    {
     public:
     ParamVector<T> test;
    
     template<T2> ParamVectorConsumer<T2> convert()
     {
       ParamVectorConsumer<T2> ret;
       ret = this->...
    }
    
    0 讨论(0)
  • 2021-01-06 14:14

    You are lost because you can't do it - the two types are completely different. Whenever you come across the need for a cast in your code, you should examine both your code and your design very closely - one or both is probably wrong.

    0 讨论(0)
  • 2021-01-06 14:19

    I'm not sure but maybe you need some like this:

    template< typename TypeT >
    struct ParamVector
    {
        template < typename NewTypeT >
        operator ParamVector< NewTypeT >()
        {
            ParamVector< NewTypeT > result;
            // do some converion things
            return result;
        }
    
        template< typename NewTypeT >
        ParamVector( const ParamVector< NewTypeT > &rhs )
        {
            // convert
        }
    
        template < typename NewTypeT >
        ParamVector& operator=( const ParamVector< NewTypeT > &rhs )
        {
            // do some conversion thigns
            return *this;
        }
    
    
    };
    ParamVector< double > d1;
    ParamVector< float > f1;
    f1 = d1;
    

    You can choose use conversion operator or operator= - I've provided both in my example.

    0 讨论(0)
提交回复
热议问题