2016-12-30 64 views
2

我最近正在研究一个C++库,在那里我设计了一个模板类,出于效率和安全的原因,我们需要特别是非多态的。为了确保以后我没有忘记这一点,并意外地破坏了一切,我认为我会成为一个好公民,并为此添加静态断言。确保模板类不是多态的?

我最初尝试是这样的:

template <typename T> class VirtualVerboten { 
    ... 

    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); // Error! 
}; 

这并不是因为编译,在我使用VirtualVerboten的时间,这是一个不完整的类型。如果这是一个非模板类,我只是把static_assert类型之后:

class NonTemplateVirtualVerboten { 
    ... 
} 
static_assert(!std::is_polymorphic<NonTemplateVirtualVerboten>::value, 
       "This should not be polymorphic."); 

但由于这是一个模板类,使得“模板static_assert”的类似想法是不合法的:

template <typename T> class VirtualVerboten { 
    ... 

}; 

template <typename T>    
static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Error! 

我想出了解决的办法是找到VirtualVerboten内的成员函数,将有可能被用来当模板实例化(具体而言,构造函数),然后把静态断言在那里:

template <typename T> class VirtualVerboten { 
    VirtualVerboten(); 
}; 

template <typename T> 
VirtualVerboten<T>::VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Yay! 
    doSomeActualThingsAtRuntime(); 
} 

这是有效的,只是它依赖于这个特定的构造函数实际上会被调用并因此实例化的事实,如果有多个可以调用的构造函数会失败。

有没有一种“万无一失”的方式来在这里添加这个静态断言?我明白为什么原始代码会产生一个错误,为什么你不能有模板静态断言,所以这更像是“我错过了另一种这样做的方式吗?”而不是“这就是为什么你所做的不起作用。”

+0

呃?构造函数?不得不在某个地方建造这个类。在那里推你的静态断言。 –

+0

@SamVarshavchik这就是我最终做的。也许我应该编辑这个问题,使其更清晰。 – templatetypedef

+0

您只需要将某个类型封装在某个相关的东西中,这样只会在第二阶段中检查静态断言。 –

回答

3

它已经通过@JerryCoffin's comment表示。最好的方法是在析构函数中使用static_assert。即

template <typename T> 
class VirtualVerboten { 
public: 
    ~VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); 
    } 
}; 

由于析构函数可以是只有1,它保证了每当有它的对象的实例化的static_assert被选中。


IMO,另一种优雅的方式是创建一个实用工具类&继承相同的,如:

template<typename T> 
struct NonPolymorphic 
{ 
    ~NonPolymorphic() 
    { static_assert(!std::is_polymorphic<T>::value, "This should not be polymorphic."); } 
}; 

template <typename T> 
class VirtualVerboten : NonPolymorphic<VirtualVerboten<T>> 
{ 
    // ... 
}; 
0

final关键字是一个C++ 14功能,不允许继承类。如果该类是继承的,则代码将不会编译。例如:

template <typename T> 
class VirtualVerboten final { 
    ... 
} 

如果有人试图继承它...

class Derived : public VirtualVerboten<int> { 
    ... 
} 

编译器会抱怨

+1

问题是关于多态,而不是继承。两者是非常密切相关的,但是没有多态性的继承(即使用虚函数)是可能的。 cppreference将“is_polymorphic”类型特征描述为“声明或继承至少一个虚拟函数的非联合类”。哪些应该提供关于OP试图排除的类的类型的线索。 –

+0

奇怪的是,在我考虑使用继承的情况下,不得不使用多态,所以这种方法实际上并不适用于我的情况。 – templatetypedef