Tomilov Anatoliy
Tomilov Anatoliy

Reputation: 16741

How to introduce static_assert into template variable definition

How to introduce static_assert into template variable definition?

My attemption is to use lambda function:

#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;
}

But for non-moveable objects it is impossible to construct the value object in such a manner.

Using comma operator I can't perform value-initialization in form F f = ([] () { static_assert(std::is_default_constructible< F >{}); }(), {});.

I can't use additional template parameter in form , typename = decltype([] () { static_assert(std::is_default_constructible< F >()); }), due to it is an error lambda expression in an unevaluated operand.

Disabling instantiation by SFINAE is not the solution. I do need static_assert to say user about error explicitly.

It would be nice if static_assert return void or bool.

Upvotes: 2

Views: 710

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171413

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{};
}

Or so the check appears directly in the variable 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{};
}

Upvotes: 5

Related Questions