19

我试图了解 的用处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();
    }
};

仅当HelperT的专门化支持 size of 时才支持Foo。例如,和都受支持。但是,假设用户尝试构建一个. 通常,这会产生错误,因为未定义Helper for的专业化,这是预期的行为。Foo<long>Foo<unsigned long>Foo<bool>bool

有没有什么方法可以static_assert在这个设计中使用来为这个界面的用户提供更多有用的错误?

此外,我还想限制用户使用特定类型,即使大小可能是正确的。例如,Foo<float>不应该被允许。现在,我知道执行此操作的唯一方法是通过文档中的粗体注释。:)

4

3 回答 3

27

如果它只能用于模板类的特化,那么让默认模板类引发一个静态断言:

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
于 2013-07-16T14:31:23.717 回答
10

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 年内找到了答案:)

于 2017-08-10T04:59:56.200 回答
1

通过结合此处的答案和评论,我为这个问题找到了更好的解决方案。

我可以像这样定义一个静态类型检查器:

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!");
于 2013-07-16T15:04:04.887 回答