C++: casting non constant to constant - c++

I want to convert a non constant variable to constant variable. I tried using const_cast but still the following program is giving error that ‘bitsize1’ cannot appear in a constant-expression. What am i doing wrong ?
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
int main(){
int l = 3; // taken input from user
int bitsize2 = (l * 2);
int bitsize1 = const_cast<int&>(bitsize2);
string temp = "100101";
bitset<const_cast<int&>(bitsize2)> baz (temp);
cout << baz;
return 0;
}

const_cast is used to cast const away not to make something const. If you want constant expression the easiest way in post-C++11 programming is to use constexpr:
constexpr int l = 3;
constexpr int bitsize2 = l * 2;
The input from user cannot be a compile time constant expression so you must figure out something else.

Templates are expanded in compile time, this means that all template arguments should be known when compiling. Obviously user input is runtime data thus cannot be used as a template argument.

As stated by others, you cannot deduce template parameters at runtime.
You should look into using boost's dynamic bitset.
It exists for the exact problem that you have run into.
"The dynamic_bitset class is nearly identical to the std::bitset class.
The difference is that the size of the dynamic_bitset (the number of
bits) is specified at run-time during the construction of a
dynamic_bitset object, whereas the size of a std::bitset is specified
at compile-time through an integer template parameter."

Related

C++ pointer of array: why cannot use an array defined by indirectly computed const var in function begin(array)?

Error message in text:
I'm studying the book C++ Primer and encountering a problem listed below when coding an answer for one exercise:
#include<iostream>
#include<vector>
using namespace std;
int main() {
int i = 3;
const int ci = 3;
size_t si = 3;
const size_t csi = 3;
int ia[i];
int cia[ci];
int sia[si];
int csia[csi];
int another_a[] = {1,2,3};
int *pi = begin(ia); // error here
// no instance of overloaded function "begin" matches the argument list --
// argument types are: (int [i])
int *pci = begin(cia);
int *psi = begin(sia); // error here
// no instance of overloaded function "begin" matches the argument list --
// argument types are: (int [si])
int *pcsi = begin(csia);
int *p_ano = begin(another_a);
vector<int> v = {1,3,4};
const int m = v.size();
const size_t n = v.size();
int ma[m];
int na[n];
int *pm = begin(ma); // error here
// no instance of overloaded function "begin" matches the argument list --
// argument types are: (int [m])
int *pn = begin(na); // error here
// no instance of overloaded function "begin" matches the argument list --
// argument types are: (int [n])
system("pause");
return 0;
}
I can understand that the first two errors are because that those two arrays are not defined using an constant variable.
But why the last two, even if I have converted the size of the vector into a constant variable, the compiler still reports an error?
I'm quite confused about this, I would appreciate a lot for your kindly answer or discussion no matter it works or not.
First and foremost, you are using a compiler extension, but more on that later.
The standard begin overload which works for you is a template that accepts a reference to an array with a size that is a constant expression. In a nutshell, constant expressions are those expressions that a compiler can evaluate and know the value of during compilation.
A constant integer initialized with a constant expression like const int ci = 3;, can be used wherever a constant expression is required. So ci is, for all intents an purposes, a constant expression itself (equal to 3).
Modern C++ has a way to make such varaibles stand out as intended constant expressions, it's the constexpr specifier. So you could define ci like this:
constexpr int ci = 3;
It's exactly like your original code. But the same will not work for const int m = v.size();. Because constexpr requires a true constant expression as an initializer, unlike const. For a const variable is not necessarily a constant expression. It can just be a run-time variable that you cannot modify. And this is the case with m.
Because m is not a constant expression, what you defined is a variable length array. A C feature that is sometimes introduced as an extension by C++ compilers. And it doesn't gel with the std::begin template, which expects the array extent to be a constant expression.
Declaring arrays with non constant indexes isn't standard c++.
If you need dynamically sized arrays use std::vector.
Declaring a variable as const doesn't make it a compile time constant (required to declare a fixed sized array) it just means you can't modify it after it is declared.

How to accomplish C++11 compile time class static member initialization on a bitset?

I'm attempting to do the following:
Say I have a class, A, and I have a static member variable, static_bit_id, that is a bitset<128>. At compile time, I want to create an ID that is a one hot bit of my choosing using bitset. I have a function that does this for me onehotbits(int n). for example:
bitset<128> b = onehotbits(4) // 0....01000
At compile time I want to assign to a static member of class A in such a way:
//in A.h
class A{
public:
const static bitset<128> bits;
};
// in A.cpp
const bitset<128> A::bits = onehotbits(1);
Previously this pattern worked with a constexpr function that instead of bitset, took uint64_t's and shifted them. Now doing the same with bitsets violates constexpr rules since operator << for bitset< T > is not a constexpr.
I can't think of a way to accomplish this using constexpr, or in a namespace safe way in general. I can initialize bitset<128> with a string, but that violates constexpr.
I'm currently getting around this problem via:
const bitset<128> A::bits = bitset<128>(1) >> n;
which seems to violate DRIP, the only way to get rid of this problem appears to use a MACRO, which wouldn't be necessary if I could just use >> operator for bitset.
Note I want to avoid using other libraries for this, especially not boost, that is overkill.
Note, while my question is similar to Initializing c++ std::bitset at compile time it is not the same, since the solution there does not work for my problem (since I'm not simply using a literal, but a literal that would have to be created at compile time via some input)
Does this solve your problem?
constexpr auto onehotbits(int i)
{
return 1<<(i-1);
}
class A{
public:
constexpr static std::bitset<128> bits{onehotbits(4)};
};
constexpr std::bitset<128> A::bits;
Calling it via
int main()
{
for(int i=0;i<128;++i)
{
std::cout<<A::bits[i]<<" ";
}
}
yields
0 0 0 1 0 0 0 0 ...
DEMO
With regard to the question whether the shift-operator is constexpr, see here. Didn't get that so far ... if not, the same behavior can attained via a template class.

Gaining access to the tuple by string template param

A standard tuple in C++ 11 allows access by the integer template param like this:
tuple<int, double> test;
test.get<1>();
but if I want get access by the string template param:
test.get<"first">()
how can I implement it?
You can create custom constexpr cast function. I just wanted to show that what the OP wants is (almost) possible.
#include <tuple>
#include <cstring>
constexpr size_t my_cast(const char * text)
{
return !std::strcmp(text, "first") ? 1 :
!std::strcmp(text, "second") ? 2 :
!std::strcmp(text, "third") ? 3 :
!std::strcmp(text, "fourth") ? 4 :
5;
}
int main()
{
std::tuple<int, double> test;
std::get<my_cast("first")>(test);
return 0;
}
This can be compiled with C++11 (C++14) in GCC 4.9.2. Doesn't compile in Visual Studio 2015.
First of all, std::tuple::get is not a member function. There is a non-member function std::get.
Given,
std::tuple<int, double> test;
You cannot get the first element by using:
std::get<"first">(test);
You can use other mnemonics:
const int First = 0;
const int Second = 1;
std::get<First>(test);
std::get<Second>(test);
if that makes the code more readable for you.
R Sahu gives a couple of good mnemonics, I wanted to add another though. You can use a C style enum (i.e. non-class enum):
enum TupleColumns { FIRST, SECOND };
std::get<FIRST>(test);
If you combine enums with a smart enum reflection library like so: https://github.com/krabicezpapundeklu/smart_enum, then you can create a set of enums that have automatic conversions to and from string. So you could automatically convert column names into enums and access your tuple that way.
All this requires you to commit to your column names and orders at compile time. In addition, you'll always need to use string literals or constexpr functions, so that you can get the enum value as constexpr to use it this way.
constexpr TupleColumns f(const char *);
constexpr auto e = f("first");
std::get<e>(test);
I should probably add a warning at this point: this is all a fairly deep rabbit hole, fairly strong C++ is required. I probably would look for a different solution in the bigger picture, but I don't know your bigger picture well enough, nor do I know the level of your C++ nor your colleagues (assuming you have them).

Compile- vs run-time const variable assignment and allocation of vlas in C++

I was working on a template function with non-type parameters (to avoid dynamic allocation of arrays) when a number of questions arose. My first question regards compile-time variable assignment. This arose from the following attempts at calls to the template function:
template<int n>
int *getDegrees(int A[][n]) {
//return degrees
}
int main(int argc, char **argv) {
int n = 10;
int A[n][n];
int *degs = getDegrees<n>(A);
}
Here, we have two errors: first, the compiler is unable to resolve the call to getDegrees(A):
main.cc:27: error: no matching function for call to ‘getDegrees(int [(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)][(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)])’
Second, we're unable to use n in the template call as it isn't a constant expression. Simply making n constant does resolve the issues
const int n = 10;
however, if I were to do
int m = 10;
const int n = m;
we get the same errors. While the second assignment may be allowed by the compiler, is it considered bad form to do so? Additionally, why would making n constant make a difference in resolving the function call?
My other question regards vlas: is memory allocated for them on the stack or the heap (and is this compiler-dependent)? There appears to have been some controversy in even allowing them in C++, should they be avoided in favor of vectors (or similar containers)?
Appreciate any insight!
I will try to answer whatever I could get from your question.
You can change the function prototype to receive the array by reference:
template<size_t n> // see the type
int *getDegrees(int (&A)[n][n]) { // see the signature
// ...
}
In above code, we are leveraging the fact that the array has same dimensions.
However, in general case it should be:
template<size_t n1, size_t n2> // see the type
int *getDegrees(int (&A)[n1][n2]) { // see the signature
// ...
}
If the size is too big then an error is issued by the compiler to inform you. e.g. (from g++):
error: size of array ‘A’ is too large
Now coming to the other question regarding the difference between assignment of the constant integer.
In C++, the array size has to be compile time constant and
const int n = 10;
fulfills that requirement. Because the compiler can make out that, 10 is a literal number being assigned to n.
In case of,
int m = 10;
const int n = m;
Compiler finds out that the source of n is not a compile time constant itself. And thus it makes the code ill formed.

How do I use member functions of constant arrays in C++?

Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];