【发布时间】:2014-05-19 14:51:19
【问题描述】:
我尝试制作一个特征来查找方法是否为virtual: (https://ideone.com/9pfaCZ)
// Several structs which should fail depending if T::f is virtual or not.
template <typename T> struct Dvf : T { void f() final; };
template <typename T> struct Dvo : T { void f() override; };
template <typename T> struct Dnv : T { void f() = delete; };
template <typename U>
class has_virtual_f
{
private:
template <std::size_t N> struct helper {};
template <typename T>
static std::uint8_t check(helper<sizeof(Dvf<T>)>*);
template<typename T> static std::uint16_t check(...);
public:
static
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
};
测试用例:
struct V { virtual void f(); };
struct NV { void f(); };
struct E { };
struct F { virtual void f() final; }; // Bonus (unspecified expected output)
static_assert( has_virtual_f< V>::value, "");
static_assert(!has_virtual_f<NV>::value, "");
static_assert(!has_virtual_f< E>::value, "");
但我得到了error: 'void Dvf<T>::f() [with T = NV]' marked final, but is not virtual。
如果我不使用sizeof 并直接在check 中使用Dvf<T>*,我没有编译错误,但check 不会因为SFINAE 中的“坏”类型而被丢弃:(。
检测方法是否为virtual 的正确方法是什么?
【问题讨论】:
-
Sfinae 不会“查看”类的定义内部,它不在 “直接上下文” 中(参见 14.8.2/8)。
-
我很感兴趣为什么你想知道这个。通常情况下,客户端应该只关心接口而不关心幕后是否有虚拟调度。
-
我认为,您必须查看 dll 的 IL 代码才能确定调用是否是虚拟的..
-
@MatthieuM.:回复explicitly-hide-a-base-function 时,我会用更简洁的特征扩展我的解决方案。
-
@Jarod42 这种行为是预期的,因为
sizeof(Dvf<T>)实例化了Dvf<T>而Dvf<T>*没有。您不能在 SFINAE 测试期间实例化无效类,否则您会收到错误消息。至于正确的方法,不知道是否可以;尝试。
标签: c++ c++11 sfinae typetraits virtual-functions