如何在模板变量定义中引入static_assert

How to introduce static_assert into template variable definition

本文关键字:static assert 定义 变量      更新时间:2023-10-16

如何将static_assert引入模板变量定义?

我尝试使用lambda函数:

#include <type_traits>
#include <utility>
#include <cstdlib>
namespace
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
template< typename F >
F f = ([] () { static_assert(std::is_default_constructible< F >{}); }(), F{});
#pragma clang diagnostic pop
}
struct L
{
    L() = default;
    L(L const &) = delete;
    L(L &&) = delete; 
};
int
main()
{
    static_cast< void >(f< L >);
    return EXIT_SUCCESS;
}

但是对于不可移动的对象,用这种方式构造值对象是不可能的。

使用逗号操作符,我不能在形式F f = ([] () { static_assert(std::is_default_constructible< F >{}); }(), {});中执行值初始化。

我不能在, typename = decltype([] () { static_assert(std::is_default_constructible< F >()); })中使用额外的模板参数,因为它是lambda expression in an unevaluated operand错误。

禁用SFINAE实例化不是解决方案。我确实需要static_assert明确地告诉用户关于错误。

如果static_assert返回voidbool就好了。

template<typename T>
struct require_default_constructible {
  static_assert(std::is_default_constructible<T>{}, "is default constructible");
  using type = T;
};
namespace
{
template< typename F >
  typename require_default_constructible<F>::type f{};
}

或者检查直接出现在变量template中:

template<typename T, bool B>
struct check {
  static_assert(B, "???");
  using type = T;
};
namespace
{
template< typename F >
  typename check<F, std::is_default_constructible<F>::value>::type f{};
}