It's virtually guaranteed that if there's a discrepancy gcc has the correct behavior, because Visual Studio 2015 doesn't support c++14's extension of constexpr
: https://msdn.microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features
C++11 constexpr
functions
The function body can only contain:
- null statements (plain semicolons)
static_assert
declarations
typedef
declarations and alias declarations that do not define classes or enumerations
using
declarations
using
directives
- exactly one
return
statement
So c++11 cannot tolerate the definition of decltype(div(T{}, T{})) x{}
. It would however be acceptable to roll the ternary suggested here in a constexpr
function to achieve the same results:
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
using foo = decltype(div(T{}, T{}));
return foo{1, 0}.quot != 0 ? foo{quot, rem} : foo{rem, quot};
}
Live Example
C++14 constexpr
functions
The function body may contain anything but:
- an asm declaration
- a goto statement
- a statement with a label other than case and default
- a try-block
- a definition of a variable of non-literal type
- a definition of a variable of static or thread storage duration
- a definition of a variable for which no initialization is performed
Where a "Literal Type" is defined here, specifically for objects though, they may be aggregate types with a trivial destructor. So div_t
definitely qualifies. Thus c++14, and by extension gcc, can tolerate the definition of decltype(div(T{}, T{})) x{}
.
C++17 constexpr
functions
C++17 added support for closure types to the definition of "Literal Type", so I find it strange that both gcc and Visual Studio support the use of the lambda in the return
statement. I guess that's either forward looking support or the compiler chose to inline the lambda. In either case I don't think that it qualifies as a c++14 constexpr
function.
[Source]
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…