通过static_assert强制执行模板类型

Zee*_*bit 18 c++ templates static-assert template-specialization

我正在努力了解它的用处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();
    }
};
Run Code Online (Sandbox Code Playgroud)

美孚如果尺寸仅支持T由一个专业化的支持助手.例如,Foo<long>并且Foo<unsigned long>都受支持.但是,假设用户尝试构造一个Foo<bool>.通常,这会产生错误,因为没有定义Helper for的特化bool,这是预期的行为.

static_assert在此设计中是否有任何方法可以为此界面的用户提供更多有用的错误?

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

Yoc*_*mer 23

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

template <class T, size_t S = sizeof(T)>
struct Helper
{
   static_assert(sizeof(T) == -1, "You have to have a specialization for Helper!" );
}
Run Code Online (Sandbox Code Playgroud)

只有在没有更好的特化时才会选择默认模板类,因此断言将会上升.

您可以使用相同的技术来禁止类型,但是您将需要另一个将用于静态断言检查的模板参数.

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
};
Run Code Online (Sandbox Code Playgroud)

然后你可以尝试使用这些变量:

Helper<bool> a;  //"You have to have a specialization for Helper!"
Helper<float> b; //"You can't use float !"
Helper<int> c;   //compiles OK
Run Code Online (Sandbox Code Playgroud)

  • 这将无法正常工作 - 您需要使断言依赖(例如`static_assert(sizeof(T)== 0,...);`),否则它将在声明点处理,而不是实例化. (12认同)
  • 我相信你想要 `static_assert(false,...)`,所以它总是会跳闸。如果第一个参数为假,`static_assert` 会打印错误。 (2认同)

Aus*_*son 5

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可能在提出问题以来的四年中找到了答案:


Zee*_*bit 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;
};
Run Code Online (Sandbox Code Playgroud)

不确定标准库中是否已经存在这样的结构。无论如何,然后在Foo中,我可以使用以下方法检查类型和大小:

static_assert((sizeof(T) == sizeof(long) || sizeof(T) == sizeof(int)) && !CheckTypes<T, float>::value, "Error!");
Run Code Online (Sandbox Code Playgroud)

  • 确实如此,std::is_same (2认同)