我有一个模板类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
}
答案 0 :(得分:5)
如何添加额外的模板化构造函数来收集不太专业的调用:
template <typename T>
class Foo {
public:
template<typename U>
explicit Foo(const U& x); // Undefined reference error at link time
explicit Foo(const T& x) { kBitCount = sizeof(T); }
// ...
};
如果您正在使用C ++ 11,则不必创建丑陋的未定义外部错误 - 您只需使用= delete
:
template<typename U>
explicit Foo(const U& x) = delete;
答案 1 :(得分:1)
Cameron解决方案的替代方案有一个构造函数,如果使用了错误的类型,它在编译时会失败:
template <typename T>
class Foo {
public:
template<
typename U,
typename = typename std::enable_if<std::is_same<U, T>{}>::type
>
explicit Foo(const U& x) { ... }
};
可以使用几个标准别名缩短。