static_assert not allowed in enums

closed account (3hM2Nwbp)
Can anyone find something in the standard that explicitly disallows this?

I'm going from section 7.1 where it is stated that:

Standard wrote:
A declaration occurs in a scope (3.3); the scope rules are summarized in 3.4. A declaration that declares a
function or defines a class, namespace, template, or function also has one or more scopes nested within it.


Jumping to section 3.3 we find that there exist block scope, function prototype scope, function scope, namespace scope, class scope, enumeration scope, and template parameter scope.

I find nothing that states that static_assert declarations cannot be used in any of those scopes, yet only block, function, class, and namespace scopes allow for it with clang.

Thanks be to anyone who can clarify this discrepancy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static_assert(true, "");				// namespace scope (good))

class X
{
	static_assert(true, "");			// class scope (good))
};

int main()
{
	static_assert(true, "");			// function scope (good)
	{
		static_assert(true, "");		// block scope (good)
	}
}

enum Y
{
	static_assert(true, "");			// enumeration scope (BOOM)
};

template<typename T 
	static_assert(true, "")>			// template parameter scope (BOOM)
void test(static_assert(true, ""))			// function prototype scope (BOOM)
{
	
}
Last edited on
A declaration occurs in a scope (3.3); the scope rules are summarized in 3.4. A declaration that declares a
function or defines a class, namespace, template, or function also has one or more scopes nested within it.


The next line is relevant:
These nested scopes, in turn, can have declarations nested within them.


7.1.1 lets us know that a static_assert-declaration is a block-declaration. While I can't find anything that specifically says that a block-declaration may only be declared in a block-scope, I can't imagine the choice of names was coincidental.

In line 1 the static_assert is in the global namespace which is essentially an implicit scope that contains all other scopes. block-declarations are legal here.

Line 5: 9.2 specifically allows for a static_assert-declaration here. The declaration has class scope.

Line 10: The static_assert has block scope. Note that labels are the only things which can have function scope.

Line 12: The static_assert has block scope.

Line 18: 7.2 doesn't allow for declarations in an enumerator-list. The term "enumeration scope" only applies to scoped enums.

Line 21: See section 14.1 [temp.param]

Line 23: 3.1.2 lists parameter-declarations and static_assert-declarations as orthogonal entities (which also works for the template parameter type, I would think.)

Also, static_assert doesn't meet the definition of parameter as the standard defines it (1.3.14)

[edit: redundant line removed.]
Last edited on
Simulated static_assert for enum:
1
2
3
4
5
#include <type_traits>

constexpr int N = 5 ;

enum U : std::conditional< (N>0), int, double >::type { V = N };

And for template parameters, SFINAE with std::enable_if<>
closed account (3hM2Nwbp)
Thanks for the info. It seems that I have a long way to go in fully understanding how to interpret "standardese" in terms of where to find relevant content. I suppose that time and experience are the only factors that will change this.

The reason why I'm prying this information is that I'm going to be doing an informal "Modern C++" presentation series for CS students at a university. I want to make damn sure that I can answer whatever questions that might arise, and thus need to have a comprehensive understanding of all of the features that I will be describing. IE. Why can't I use this in an enum?
Last edited on
Topic archived. No new replies allowed.