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 ]