Necktwi
Necktwi

Reputation: 2617

what is the right way to define typecast operator template in C++

this code here is my attempt to define a template to typecast or assignment operator. Problem is, this is not calling typecast function template at line 27 while typecasting the object.

#include <iostream>
#include <string>

using namespace std;
struct FFJSON{
    template <typename T>
    FFJSON& operator=(T const& t){
        cout << "Assigning the object" << endl;
        ts=(void*)&t;
        return *this;
    };
    FFJSON& operator=(const char* s){return *this;};
    FFJSON& operator=(const string& s){return *this;};
    FFJSON& operator=(const int& i){return *this;};
    FFJSON& operator=(const unsigned int& i){return *this;};
    template <typename T>
    operator T(){
        cout << "Returning the object." << endl;
        return *ts;
    }
    void* ts;
};
int main(int argh, char** argv) {
    FFJSON f;
    timespec tt = {3,2};
    f = tt;
    timespec& t=(timespec&)f;
    cout << "sec:"<<t.tv_sec<<endl;
    cout << "usec:"<<t.tv_nsec<<endl;
    return 0;
}

Actual output:

Assigning the object
sec:126885484802960
nsec:4197094

Expected output:

Assigning the object
Returning the object
sec:3
nsec:2

The similar scenario is giving typecast operator not defined compile time error in an another program.

Upvotes: 0

Views: 206

Answers (2)

Andreas H.
Andreas H.

Reputation: 1811

timespec& t=(timespec&)f; cannot use the typecast operator because you are casting to timespec& and not to timespec.

You have to implement

 operator T&(){
        cout << "Returning the object." << endl;
        return *reinterpret_cast<T*>(ts);
    }

to make this work.

Please do not use C-style casts in C++ modules. Use static_cast<>, dynamic_cast<>, reinterpret_cast<> and - if you really have to - const_cast<> instead.

I am not sure what you are trying to achieve, but the following implementation of the assignment operator copies the source value and should work for temporary objects and the typecast operator checks if the conversion may be valid.

class FFJSON
{
public:
    template <typename T>
    inline FFJSON& operator=(T const& t){
        cout << "Assigning the object" << endl;
        assert(std::is_trivially_copyable<T>::value );
        data.resize(sizeof(t));
        *reinterpret_cast<T*>(data.data()) = t;
        return *this;
    };

    template <typename T>
    inline operator T(){
        cout << "Returning the object." << endl;
        assert(sizeof(T) <= data.size());
        return *reinterpret_cast<T*>(data.data());
    }

private:
    std::vector<char> data;
};

Upvotes: 2

Brian Bi
Brian Bi

Reputation: 119089

template <typename T> operator T() is fine, but such T can only be deduced to a non-reference type so this operator will not be used to convert to the type timespec&. Instead, your cast is a reinterpret_cast, which never performs a user-defined conversion.

In order to write a conversion operator that can produce an lvalue, you would need to write template <typename T> operator T&().

BTW, you can't dereference a void pointer. If your operator template were ever instantiated, you would get a compilation error because of that.

Upvotes: 3

Related Questions