我正在尝试理解static_assert
的用处,我想知道它是否可以帮助我执行设计,如果是,那么如何。
我有一个通用模板类,它将自己的实现隐藏在另一个模板类中,该模板类根据模板类型的大小进行部分专用。以下是此设计的简要概述:
template <class T, size_t S = sizeof(T)>
struct Helper;
template <class T>
struct Helper<T, sizeof(long)>
{
static T bar();
};
// ... other specializations ...
template <class T>
class Foo
{
public:
T bar()
{
return Helper<T>::bar();
}
};
仅当帮助程序的专业化支持T
的大小时,才支持 Foo 。例如,Foo<long>
和Foo<unsigned long>
都受支持。但是,假设用户尝试构造Foo<bool>
。通常,这会产生错误,因为bool
的 Helper 的特化没有定义,这是预期的行为。
有没有办法在此设计中使用static_assert
为此界面的用户提供更多有用的错误?
此外,我还想限制用户使用特定类型,即使大小可能正确。例如,不应允许Foo<float>
。现在,我知道强制执行此操作的唯一方法是通过文档中的大胆注释。 :)
答案 0 :(得分:18)
如果它只能用于模板类的特化,那么让默认模板类引发一个静态断言:
template <class T, size_t S = sizeof(T)>
struct Helper
{
static_assert(sizeof(T) == -1, "You have to have a specialization for Helper!" );
}
只有在没有更好的专业化时才会选择默认模板类,因此断言将会上升。
您可以使用相同的技术来禁止类型,但是您需要另一个模板参数来用于静态断言检查。
template <class T, class G = T, size_t S = sizeof(T)>
struct Helper
{
static_assert(sizeof(G) == -1, "You have to have a specialization for Helper!" );
}
template <class G>
struct Helper<float,G>
{
static_assert(sizeof(G) == -1, "You can't use float !" );
}
template <>
struct Helper<int>
{
//This is a good specialization
};
然后你可以尝试使用这些变量:
Helper<bool> a; //"You have to have a specialization for Helper!"
Helper<float> b; //"You can't use float !"
Helper<int> c; //compiles OK
答案 1 :(得分:4)
http://en.cppreference.com/w/cpp/header/type_traits
std::is_base_of
和std::is_convertible
可以帮助解决您的第一个问题,对于第二个问题,
static_assert(!std::is_same<float,T>(),"type can't be float");
希望这可以帮助那些偶然发现这个问题的人,假设OP可能会在被问到的4年内找到答案:)
答案 2 :(得分:0)
通过在此处结合答案和评论,我找到了解决此问题的更好解决方案。
我可以像这样定义静态类型检查器:
template <class A, class B>
struct CheckTypes
{
static const bool value = false;
};
template <class A>
struct CheckTypes<A, A>
{
static const bool value = true;
};
不确定标准库中是否已存在此类结构。无论如何,然后在 Foo 中,我可以使用以下方法检查类型和大小:
static_assert((sizeof(T) == sizeof(long) || sizeof(T) == sizeof(int)) && !CheckTypes<T, float>::value, "Error!");