简体   繁体   中英

Advantages of static_cast over explicit instantiation/construction?

Considering the following function template func declared within MyClass class template:

template < T >
class MyClass {
public:
    MyClass() = default;

    // ...

    template < typename oT >
    oT func() {
        return static_cast< oT >(_m);  // alternative, return oT(_m);
    }

    // ...

 protected:
    T _m;
};

Is there any advantage in calling static_cast< oT >(_m) over explicit instantiation ie oT(_m) ?

oT(_m) will allow many more conversions than is probably intended. If static_cast<oT>(_m) wouldn't be possible, then oT(_m) will also try a const_cast , static_cast followed by const_cast , reinterpret_cast and reinterpret_cast followed by const_cast .

For example if T is const int* and oT is double* , then oT(_m) will succeed, while static_cast<oT>(_m) will fail. But using the result from oT(_m) as if it was a pointer to a double will result in undefined behavior.

If T and oT are pointers to classes that is maybe even more dangerous, since oT(_m) will always compile, whether or not there is an inheritance relation between the two classes.

Even static_cast allows for some conversions that may not be intended. For example it can downcast pointers to classes.

Another alternative is simply return _m; . This is weaker than both variants above. It will only allow for copy-initialization. However that might be too weak depending on your use case. For example it will not use explicit constructors and conversion functions. On the other hand before C++17 it doesn't require oT to be move-constructible, which the first two variants do require before C++17.

So you will need to decide what casts are supposed to be allowed and which ones are supposed to fail.

However, nothing prevents a user from calling func<T>() to obtain the original type anyway and the user can then simply cast it however they like, so I am not sure what is gained here over a simple getter.

Even more so, the user can in either case call func<T&>() and will get a reference to the member, thereby making the protected somewhat pointless. Maybe the allowed types T need to be constrained via SFINAE/requires-clause.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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