【发布时间】:2014-03-17 20:44:00
【问题描述】:
我有一个模板类 Foo,它的类型是 T。当我创建 T 的实例时,我想确保构造函数传递相同的类型。
编译器会确保这一点,除了隐式转换的小细节。我想阻止这些,但我不知道是否有一个好的方法可以做到这一点。编译器标志在这里不是一个选项。
我实际上是在尝试防止从 double 到 float 的隐式转换,因为我的 Foo 类正在做一些有趣的魔法,这些魔法会在所说的演员表上爆炸。有什么建议吗?
template <typename T>
class Foo {
public:
explicit Foo(const T& x) {kBitCount = sizeof(T); }
size_t kBitCount;
size_t mySize(){ return kBitCount; } // Size used to demonstrate
};
int main(int argc, char *argv[])
{
short sh = 5;
Foo<int> foo_int_from_short(sh); // I want this to fail
std::cout << "size:" << foo_int_from_short.mySize() << std::endl; // prints 4
Foo<short> foo_sh((unsigned int)5); // I want this to fail
std::cout << "size:" << foo_sh.mySize() << std::endl; // Prints 2
return 0;
}
更新了解决方案,C++11 允许编译时检查
#include <limits>
#include <typeinfo>
#if __cplusplus > 199711L // If C++11 or greater
#include <type_traits>
#endif
template <typename T>
class Foo {
public:
#if __cplusplus > 199711L
// Prevent implict type conversions at compile time
template<
typename U,
typename = typename std::enable_if< std::is_same<U, T >::value >::type
>
explicit Foo(const U& x)
{
#else
template< typename U >
explicit Foo(const U& x)
{
// Assert on implict type conversions, run time
if(typeid(U).name() != typeid(T).name())
{
std::cerr << "You're doing an implicit conversion with Foo, Don't" << std::endl;
assert(typeid(U).name() == typeid(T).name()); // Or throw
}
#endif
}
【问题讨论】: