c++ constexpr implementation of std::vector [duplicate] - c++

This question already has an answer here:
Compiler disagreement on using std::vector in constexpr context
(1 answer)
Closed 24 days ago.
Why doesn't clang support constexpr std::vector?
I have a basic implementation which uses std::allocator and std::construct_at/std::destroy_at, and it works well in a constexpr function.
https://godbolt.org/z/GfeE4KEPx
constexpr auto test() -> int {
Vec<int> a;
a.push(1);
a.push(2);
a.push(3);
a.push(4);
int s = 0;
for (int i : a) {
s += i;
}
return s;
}
auto main() -> int {
constexpr int a = test();
static_assert(a == 10);
return 0;
}

c++20 has constexpr std::vector and both gcc's libstdc++ (since gcc 12) and clang's libc++ (since clang 15) implement it: https://godbolt.org/z/qsfhxWe6K.

Related

Does C++11 or C++14 support "&& const" in declaration

Is the following definition (from a piece of C++ source code) valid?
struct Test_
{
int i;
Test_(int j) : i(j) { }
int try() && { return i; }
int try() && const { return -i; }
};
I mean if it's valid to put const after &&.
This code is about overload resolution with ref-qualifier.
I know const && is valid. I wonder if "&& const" is supported in C++11 or C++14.

Discrepancy with lambda conversion constructor in GCC/MSVC

Which one, if not both, is breaking spec? Tried with MSVC on both MSVC 2013 and MSVC Nov 2013 CTP, GCC was MinGW x64 4.9.1 with -std=c++11.
template<typename ret_type>
class memoizer
{
using func_type = ret_type(*)(const int);
const func_type func;
std::map<int, ret_type> cache;
public:
memoizer(func_type func) : func(func)
{
}
ret_type operator [](const int n)
{
const auto it = cache.find(n);
if(it != cache.end())
return it->second;
return cache[n] = func(n);
}
};
//works in GCC but not MSVC
//error C2065: 'fib' : undeclared identifier
memoizer<int64_t> fib([](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
});
//works in MSVC but not GCC
//error: conversion from '<lambda(int)>' to non-scalar type 'memoizer<long long int>' requested
memoizer<int64_t> fib = [](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
};
This seems to stem from the way they're handling lambda types differently, and when they consider a variable to be defined.
GCC is right.
For your first form:
A variable is considered declared at the end of its declarator, which is before its initialiser. This is why the this form is valid. The famous example is int i = i;, which is syntactically valid and initialises i with its own (indeterminate) value.
For your second form:
Your initialisation with = fails because you have two user-defined conversions. (The lambda type's conversion operator is considered user-defined.) It is analogous to
struct A { };
struct B { B(A) { } };
struct C { C(B) { } };
A a;
C c1(a); // okay
C c2 = a; // error

Why does the order of the class members matter? [duplicate]

This question already has an answer here:
decltype in class method declaration: error when used before "referenced" member is declared
(1 answer)
Closed 8 years ago.
My compiler is GCC 4.9.0.
struct A {
int n;
auto f() -> decltype(n) { // OK
return n;
}
};
struct B {
auto f() -> decltype(n) { // error: 'n' was not declared in this scope
return n;
}
int n;
};
int main() {
return A().f() + B().f();
}
Why does the order of the class members matter?
The declarations are compiled in order. It's the same reason you can't write:
int y = x;
int x = 5;
The bodies of inline functions (incl. c-tor initiailizer lists) are processed later (parsed first of course, but the names aren't looked up until after the class definition is complete) so they can refer to class members that are on later lines.

Enforce compile-time constexpr [duplicate]

This question already has answers here:
How to ensure constexpr function never called at runtime?
(5 answers)
Closed 1 year ago.
In C++11 we get constexpr:
constexpr int foo (int x) {
return x + 1;
}
Is it possible to make invocations of foo with a dynamic value of x a compile time error? That is, I want to create a foo such that one can only pass in constexpr arguments.
Replace it with a metafunction:
template <int x> struct foo { static constexpr int value = x + 1; };
Usage:
foo<12>::value
Unfortunately, there is no way guarantee that a constexpr function, even the most trivial one, will be evaluated by the compiler unless absolutely necessary. That is, unless it appears in a place where its value is required at compile time, e.g. in a template. In order to enforce the compiler to do the evaluation during compilation, you can do the following:
constexpr int foo_implementation (int x) {
return x + 1;
}
#define foo(x) std::integral_constant<int, foo_implementation(x)>::value
and then use foo in your code as usual
int f = foo(123);
The nice thing about this approach is that it guarantees compile-time evaluation, and you'll get a compilation error if you pass a run-time variable to foo:
int a = 2;
int f = foo(a); /* Error: invalid template argument for 'std::integral_constant',
expected compile-time constant expression */
The not so nice thing is that it requires a macro, but this seems currently inevitable if you want both guaranteed compile-time evaluation and pretty code. (I'd love to be proven wrong though!)
Yes, it can now be done in purely idiomatic C++, since C++20 added support for this kind of problem. You annotate a function with consteval and can be sure that it's being evaluated during compile time. https://en.cppreference.com/w/cpp/language/consteval
consteval int foo( int x ) {
return x + 1;
}
int main( int argc, char *argv[] )
{
return foo( argc ); // This will not compile
return foo( 1 ); // This works
}
Also see this godbolt.org demo in the 3 most relevant compilers.
I would use static_assert as shown in this example
#include<iostream>
constexpr int foo(int x) {
return x+1;
}
int main() {
// Works since its static
std::cout << foo(2) << std::endl;
static_assert(foo(2) || foo(2) == 0, "Not Static");
// Throws an compile error
int in = 3;
std::cout << foo(in) << std::endl;
static_assert(foo(in) || foo(in) == 0, "Not Static");
}
For more infos: http://en.cppreference.com/w/cpp/language/static_assert

One member enums in C++ [duplicate]

This question already has answers here:
static const Member Value vs. Member enum : Which Method is Better & Why?
(6 answers)
Closed 10 years ago.
I stumbled upon this answer to a question about powers of integers in c++: https://stackoverflow.com/a/1506856/5363
I like it a lot, but I don't quite understand why the author uses one element enums as opposed to some integer type explicitly. Could someone explain?
AFAIK this has to do with older compilers not allowing you to define compile-time constant member data. With C++11 you could do
template<int X, int P>
struct Pow
{
static constexpr int result = X*Pow<X,P-1>::result;
};
template<int X>
struct Pow<X,0>
{
static constexpr int result = 1;
};
template<int X>
struct Pow<X,1>
{
static constexpr int result = X;
};
int main()
{
std::cout << "pow(3,7) is " << Pow<3,7>::result << std::endl;
return 0;
}