static_cast 相对于显式实例化/构造的优点?

joa*_*dre 0 c++ casting static-cast

考虑在类模板func中声明以下函数模板:MyClass

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

    // ...

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

    // ...

 protected:
    T _m;
};
Run Code Online (Sandbox Code Playgroud)

static_cast< oT >(_m)调用显式实例化有什么优势吗oT(_m)

use*_*522 5

oT(_m)将允许比预期更多的转换。如果static_cast<oT>(_m)不可能,那么oT(_m)也会尝试 a const_caststatic_cast然后是const_castreinterpret_cast然后reinterpret_castconst_cast

例如,如果Tisconst int*oTis double*,则 thenoT(_m)将成功,而 whilestatic_cast<oT>(_m)将失败。但是将 from 的结果oT(_m)当作指向 a 的指针使用double会导致未定义的行为。

如果ToT是指向类的指针,则可能更危险,因为oT(_m)无论两个类之间是否存在继承关系,都将始终编译。

甚至static_cast允许一些可能不是预期的转换。例如,它可以向下转换指向类的指针。

另一种选择很简单return _m;。这比上面的两个变体都要弱。它只允许复制初始化。然而,根据您的用例,这可能太弱了例如,它不会使用显式构造函数和转换函数。另一方面,在 C++17 之前,它不需要oT可移动构造,而前两个变体在 C++17 之前确实需要移动构造。

因此,您需要决定哪些强制转换应该被允许,哪些强制转换应该失败。

然而,无论如何,没有什么可以阻止用户调用func<T>()来获取原始类型,然后用户可以根据自己的喜好简单地转换它,所以我不确定通过简单的 getter 在这里可以获得什么。

更重要的是,在任何一种情况下,用户都可以调用func<T&>()并获得对该成员的引用,从而使这变得protected毫无意义。也许允许的类型T需要通过 SFINAE/requires-clause 进行约束。