Arrays declared globally gives out of scope error in functions - c++11

I have these arrays declared globally
char str1[] = "6541254939322816220209974565477289648317";
char str2[] = "3142522751761601737419090933147067701840";
int str1_size = strlen(str1);
int str2_size = strlen(str2);
int lcs[str1_size][str2_size];
int arrows[str1_size][str2_size];
But when I access this inside a function, it gives
lcs was not declared in this scope
also
array bound is not an integer constant before β€˜]’ token
int lcs[str1_size][str2_size];
What am I doing wrong here ?

First of all
int a[dim];
where dim isn't a compile-time know constant (constexpr by example) isn't C++ standard; maybe it's possible with some extension with some compiler but isn't C++ standard.
So, in your case
int lcs[str1_size][str2_size];
int arrows[str1_size][str2_size];
where str1_size and str2_size are normal (not constexpr, not const initialized with literals) variables, is an error.
If you could redefine str1_size and str2_size as follows
constexpt int str1_size = strlen(str1);
constexpr int str2_size = strlen(str2);
the lcs and arrows definition could works.
Unfortunately (1) str1 and str2 aren't constexpr and (2) std::strlen() isn't constexpr.
But if declare str1/str2 constexpr and write a constexpr alternative to std::strlen...
#include <iostream>
constexpr std::size_t lenStr (char const * str)
{
std::size_t ret{};
while ( *(str++) )
++ret;
return ret;
}
constexpr char str1[] = "6541254939322816220209974565477289648317";
constexpr char str2[] = "3142522751761601737419090933147067701840";
constexpr auto str1_size = lenStr(str1);
constexpr auto str2_size = lenStr(str2);
int lcs[str1_size][str2_size];
int arrows[str1_size][str2_size];
int main ()
{
}
Unfortunately the preceding code require C++14 (in C++11 it's impossible write so complex constexpr functions).
In C++11 you should write lenStr() in a recursive way
constexpr std::size_t lenStr (char const * str, std::size_t ret = 0u)
{ return *str ? lenStr(++str, ++ret) : ret; }

Related

SFINAE fails with template non-type reference argument

Consider this code:
constexpr int XX = 10;
template < auto& II > struct Ban { };
template < auto& II >
std:: true_type test(Ban<II>*);
std::false_type test(...);
and:
using BB = decltype(test(std::declval<Ban<XX>*>()));
Here I am expecting BB to be std::true_type, but it is std::false_type for both gcc-8.3 and clang-8.0. Is this a bug in these compilers?
Note that BB becomes std::true_type when I change auto& to auto. Also note that for gcc situation is the same if I use int const instead of auto, so int const& yields to std::false_type, while int const yields to std::true_type, while for clang int const& yields to std::true_type. You can find live example here.
Is there a workaround to do this kind of SFINAE with a template of non-type reference? The point is to have a utility like IsInstantiationOfBan.
Maybe instead of auto & you want decltype(auto):
#include <type_traits>
constexpr int XX = 10;
template <decltype(auto) II > struct Ban { };
template <decltype(auto) II >
std::true_type test(Ban<II>*);
std::false_type test(...);
int main()
{
using BB = decltype(test(std::declval<Ban<(XX)>*>()));
// ^ ^ be careful for brackets!
static_assert(std::is_same_v<BB, std::true_type>);
return 0;
}
[live demo]
In case of your first question, clang probably requires the const specifier before auto & to fulfil const correctness (constexpr variable is also presumably const). [example].

Variadic Template Recursion

I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.

There is a way in gcc to get a warning when a constexpr can't be evaluated at compile time?

I'm using gcc 5.1.0 (c++14) and I was trying with constexpr. Is very annoying to verify if the constexpr I've implemented are evaluated at compile time. I couldn't find any flag for get a warning about that situation.
Here is an example:
example.cpp -----------------------------------------
#include <stdlib.h>
const char pruVar[] = "12345678901234567";
[[gnu::noinline]] constexpr unsigned int myStrlen(const char* cstr)
{
unsigned int i=0;
for(;cstr[i]!=0;++i);
return i;
}
struct CEXAMPLE
{
unsigned int size;
constexpr CEXAMPLE(const char* s): size(myStrlen(s))
{
}
};
int main(void)
{
CEXAMPLE c(pruVar);
unsigned int size = myStrlen(pruVar);
void* a = malloc(c.size + size);
if (a != nullptr)
return 0;
else
return 1;
}
In the example CEXAMPLE::CEXAMPLE is evaluated at compile time including the call to myStrlen in it, but the call to myStrlen in main is being evaluated at runtime. The only way I have to know this is looking at the assembler.This website is very useful too: http://gcc.godbolt.org/
If you know how to make the compiler warn about this or something similar I'll appreciate it
myStrlen(pruVar) can be evaluated at compile time; the compiler is just choosing not to in this instance.
If you want to force the compiler to evaluate it at compile time or error if this is not possible, assign the result to a constexpr variable:
constexpr unsigned int size = myStrlen(pruVar);
^^^^^^^^^
You could also use an enum, or a std::integral_constant:
enum : unsigned int { size = myStrlen(pruVar) };
std::integral_constant<unsigned int, myStrlen(pruVar)> size;
Based on the fact that template arguments must be evaluated at compiletime a helper template can be used.
namespace helper {
template<class T, T v> constexpr T enforce_compiletime() {
constexpr T cv = v;
return cv;
}
}
#define compiletime(arg) ::helper::enforce_compiletime<decltype(arg), (arg)>()
This allows compile time enforcement without an additional constexpr variable, which is handy in order to calculate value lookup tables.
constexpr uint32_t bla(uint8_t blub) {
switch (blub) {
case 5:
return 22;
default:
return 23;
}
}
struct SomeStruct {
uint32_t a;
uint32_t b;
};
SomeStruct aStruct = {compiletime(bla(5)), compiletime(bla(6))};

How to determine if a constexpr class is built at compile time or not?

Let's consider the following code:
class A {
public:
constexpr A(int value) : m_value(value);
private:
const int m_value;
};
void f(const A& a);
f(42); // OK
f(std::rand()); // KO - How to detect this case?
Is there a way to determine if A is built at compile time or run-time?
One way to verify that an expression is indeed a constexpr is to assign it to a constexpr variable:
int main()
{
constexpr int a = f(42);
constexpr int b = f(std::rand());
return(0);
}
Since the value constexpr variables must be computable by the compiler, the assignment of b will produce an error. GCC says the following:
foo.cpp:25:35: error: call to non-constexpr function β€˜int rand()’
constexpr int b = f(std::rand());
I'm not sure if it can be done in a way to merely produce a warning, however.

string literal parameter not accepted to a constexpr function

Call to the extract function below does not work for me on g++ 4.9.0 (20130421). The error I get is that s1 is not a constant expression. If i can be initialized as constexpr then j and k should too. Is that wrong?
#include <tuple>
template <unsigned N1, unsigned N2>
constexpr bool strmatch(const char (&s1)[N1], const char (&s2)[N2], unsigned i = 0)
{
return (s1[i]==s2[i]) ?
(s1[i]=='\0') ?
true
: strmatch(s1, s2, i+1)
: false;
}
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
int main(void)
{
constexpr int i = strmatch("m0", "m0"); // OK
constexpr int j = extract(std::make_tuple(10, 20), "m0");
constexpr int k = extract(std::make_tuple(10, 20), "m1");
return 0;
}
Your code is ill-formed. The problem is that array is not a core constant expression, so can't be used in the template argument in the call to std::get:
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
Remember that constexpr functions can be called at runtime: this code would use the value of a runtime parameter to this function (array) during translation (in the evaluation of the call to strmatch).

Resources