Topic: static_assert in constexpr functions


Author: =?ISO-8859-2?Q?Andrzej_Krzemie=F1ski?= <akrzemi1@gmail.com>
Date: Sun, 17 Apr 2011 01:33:17 CST
Raw View
Hi,
In the latest C++ Standard Draft (N3291) static_assert declarations
are allowed in constexpr functions. I do not understand how they work.
Consider:

 constexpr unsigned half( int i )
 {
   static_assert( i % 2 == 0, "requires even arg" );
   return i / 2;
 }

static_assert requires a constant expression. Is "i % 2 == 0" a
constant expression or not? My intuitive understanding is that it is
not known at the time of function declaration if 'i' refers to
'constexpr' object or not. But if I try to read the standard very
formally, it looks that (as per 5.19/2), since 'i' is not "a glvalue
of integral or enumeration type that refers to a non-volatile const
object with a preceding initialization, initialized with a constant
expression," static_assert declaration is incorrect.

Is it correct interpretation that we cannot use function arguments in
static_assert declarations for constexpr functions?

Regards,
&rzej


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Bo Persson" <bop@gmb.dk>
Date: Sun, 17 Apr 2011 09:42:47 CST
Raw View
Andrzej Krzemienski wrote:
> Hi,
> In the latest C++ Standard Draft (N3291) static_assert declarations
> are allowed in constexpr functions. I do not understand how they
> work. Consider:
>
> constexpr unsigned half( int i )
> {
>   static_assert( i % 2 == 0, "requires even arg" );
>   return i / 2;
> }
>
> static_assert requires a constant expression. Is "i % 2 == 0" a
> constant expression or not? My intuitive understanding is that it is
> not known at the time of function declaration if 'i' refers to
> 'constexpr' object or not. But if I try to read the standard very
> formally, it looks that (as per 5.19/2), since 'i' is not "a glvalue
> of integral or enumeration type that refers to a non-volatile const
> object with a preceding initialization, initialized with a constant
> expression," static_assert declaration is incorrect.
>
> Is it correct interpretation that we cannot use function arguments
> in static_assert declarations for constexpr functions?
>

Correct, you cannot use the parameter value as that is not a compile
time constant.

You could use the parameter's *type* in a class template, to make sure
your object is constructed with proper types only.


Bo Persson



--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?UTF-8?B?RGFuaWVsIEtyw7xnbGVy?=<daniel.kruegler@googlemail.com>
Date: Mon, 18 Apr 2011 13:05:41 CST
Raw View
On 2011-04-17 09:33, Andrzej Krzemie  ski wrote:
>
>  Hi,
>  In the latest C++ Standard Draft (N3291) static_assert declarations
>  are allowed in constexpr functions. I do not understand how they work.
>  Consider:
>
>    constexpr unsigned half( int i )
>    {
>      static_assert( i % 2 == 0, "requires even arg" );
>      return i / 2;
>    }
>
>  static_assert requires a constant expression. Is "i % 2 == 0" a
>  constant expression or not? My intuitive understanding is that it is
>  not known at the time of function declaration if 'i' refers to
>  'constexpr' object or not. But if I try to read the standard very
>  formally, it looks that (as per 5.19/2), since 'i' is not "a glvalue
>  of integral or enumeration type that refers to a non-volatile const
>  object with a preceding initialization, initialized with a constant
>  expression," static_assert declaration is incorrect.
>
>  Is it correct interpretation that we cannot use function arguments in
>  static_assert declarations for constexpr functions?

Bo Persson already provided the correct answer to this question.

Just as an example consider that you want to make std::forward a
constexpr function (which would be *extremely* useful), you could
realize the specification by providing this overload set in namespace std:

template<class T>
constexpr T&&
forward(typename remove_reference<T>::type&  t)
{
   return static_cast<T&&>(t);
}

template<class T>
constexpr T&&
forward(typename remove_reference<T>::type&&  t)
{
   static_assert(!is_lvalue_reference<T>::value,
     "T must not be an lvalue-reference"
   );
   return static_cast<T&&>(t);
}

It was possible before as well via one further indirection, but that
indirection usually leads to worse error messages on typical
implementations because of the call stack depth involved.

HTH&  Greetings from Bremen,

Daniel Kr  gler


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]