In the code below, constexpr for the line 2 does not give an error, but line 1 does.
#include <iostream>
using namespace std;
class ComplexNum{
public:constexpr ComplexNum(int _r=0,int _i=0):r(_r),i(_i){}
private:
int r,i;
};
int randGen(){
return 10;
}
constexpr int numGen(int i,int j){
return i+j;
}
int main()
{
constexpr int i=10,j=20;
constexpr ComplexNum c3(randGen(),randGen()); //line 1
constexpr ComplexNum c4(numGen(i,j),numGen(i,j));//line 2
return 0;
}
From the knowledge I have, constexpr evaluates the expression at compile time.
Then, shouldn't the compiler be able to evaluate the expression in line 1, because it returns a constant integer (10 in this case)?. If not, how will line 2 be okay?
The compiler can't compile line one because randGen() is not constexpr. The compiler can't magically tell if a function is constexpr. Maybe it looks constexpr, but you actually want it to run at runtime. For that reason, the compiler doesn't evaluate expressions which are not marked constexpr explicitly. Do this:
#include <iostream>
using namespace std;
class ComplexNum{
public:constexpr ComplexNum(int _r=0,int _i=0):r(_r),i(_i){}
private:
int r,i;
};
constexpr int randGen(){
return 10;
}
constexpr int numGen(int i,int j){
return i+j;
}
int main()
{
constexpr int i=10,j=20;
constexpr ComplexNum c3(randGen(),randGen()); //line 1
constexpr ComplexNum c4(numGen(i,j),numGen(i,j));//line 2
return 0;
}
Related
With the following code:
#include <algorithm>
constexpr int DATA_SIZE = 5;
constexpr int A_ARRAY_ALLOWED_SIZE = 5;
constexpr int A_ARRAY_SIZE = std::min(A_ARRAY_ALLOWED_SIZE, DATA_SIZE);
constexpr int B_ARRAY_SIZE = DATA_SIZE - A_ARRAY_ALLOWED_SIZE;
class A {
int a[A_ARRAY_SIZE];
};
class B {
int b[B_ARRAY_SIZE];
};
int main()
{
A a;
if constexpr (B_ARRAY_SIZE)
{
B b;
}
return 0;
}
I'm getting compiler error (with -pedantic flag) which complains that zero-size array is not allowed. In my example the object with the zero size array is never created but looks like it is still an issue.
I was trying to workaround it with usage of std::conditional but even then I ended up with an additional function like:
constexpr int Get_B_ARRAY_SIZE()
{
if (B_ARRAY_SIZE)
return B_ARRAY_SIZE;
return 1; // workaround for zero-size array
}
What is a proper way of handling such an issue?
EDIT:
I'm aware that all of if branches should contain valid code. I'm also aware that zero-size arrays are not allowed. My question is how to refactor this code to get similar behawior like when compiling without -pedantic flag. I suspect that I can use template meta programming to achieve this purpose but I'm not sure how to do it.
If you need equivalent of std::conditional, but for values, rather than types, you can do it like this:
#include <iostream>
#include <type_traits>
template<size_t N>
struct safe_array_size : std::integral_constant<size_t, N> {};
template<>
struct safe_array_size<0> : std::integral_constant<size_t, 1> {};
int main()
{
char a[safe_array_size<0>::value];
char b[safe_array_size<1>::value];
std::cout << sizeof(a) << std::endl;
std::cout << sizeof(b) << std::endl;
}
Or using std::conditional:
#include <iostream>
#include <type_traits>
template<size_t N>
constexpr size_t safe_array_size = std::conditional_t<N==0, std::integral_constant<size_t, 1>, std::integral_constant<size_t, N>>::value;
int main()
{
char a[safe_array_size<0>];
char b[safe_array_size<1>];
std::cout << sizeof(a) << std::endl;
std::cout << sizeof(b) << std::endl;
}
if constexpr (at least, how you are using it) cannot directly work around this error because it is the class definition that is ill-formed. Whether or not you instantiate the class is irrelevant. You can fix this by ensuring that the array size is never zero with std::max:
#include <algorithm>
constexpr int DATA_SIZE = 5;
constexpr int A_ARRAY_ALLOWED_SIZE = 5;
constexpr int A_ARRAY_SIZE = std::min(A_ARRAY_ALLOWED_SIZE, DATA_SIZE);
constexpr int B_ARRAY_SIZE = DATA_SIZE - A_ARRAY_ALLOWED_SIZE;
class A {
int a[A_ARRAY_SIZE];
};
class B {
int b[std::max(B_ARRAY_SIZE, 1)];
};
int main()
{
A a;
if constexpr (B_ARRAY_SIZE)
{
B b;
}
return 0;
}
Note that std::max is constexpr as of C++14. You could implement your own max function if you are on C++11.
If you need to ensure that the class is never actually instantiated unless the array size is non-zero, the if constexpr check in the above code will handle that.
The question is within the code snippet:
#include <algorithm>
#include <utility>
#include <iostream>
struct A {
static int max(std::pair<int, int> const& pair) {
return std::max(pair.first, pair.second);
}
int use_max(std::pair<int, int> const & p, int const i) {
// 1) The following works fine:
// return std::max(i, max(p));
// 2) The following also works fine:
// using std::max;
// return max(i, this->max(p));
// 3) This does not compile, afaiu cause the A::max did
// not even got into the overload resolution list due to
// name look up rules.
using std::max;
return max(i, max(p));
// Question: What do I write here to add A::max into the
// overload resolution list, e.g., something like:
// using std::max;
// using A::max;
// return max(i, max(p));
}
};
int main() {
std::cout << A().use_max(std::make_pair(2, 3), 1);
}
using A::max; is not possible since A is a class and not a namespace.
And the answer to your query is simple:
return max(i, A::max(p));
I am not sure what else are you hoping to achieve here.
Update: Thought about it some more and you can modify code this way?
#include <algorithm>
#include <utility>
#include <iostream>
struct B {
static int max(int A, int B)
{
return std::max(A,B);
}
};
struct A:B{
static int max(std::pair<int, int> const& pair) {
return std::max(pair.first, pair.second);
}
using B::max;
int use_max(std::pair<int, int> const & p, int const i) {
return max(i, max(p));
}
};
int main() {
std::cout << A().use_max(std::make_pair(2, 3), 1);
}
I just noticed something when creating functions. In the code:
#include <iostream>
using namespace std;
int add(int a, int b = 20)
{
int r;
r = a + b;
return (r);
}
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
it will work because the function being called is on top of the caller, but if I put the function add() below the calling function in main() it won't work.
#include <iostream>
using namespace std;
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
int add(int a, int b = 20)
{
int r;
r = a + b;
return (r);
}
and the compiler will tell me that the identifier add() cannot be found.
so why do we declare functions anyway? like this:
#include <iostream>
using namespace std;
int add(int a, int b = 20);
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
int add(int a, int b)
{
int r;
r = a + b;
return (r);
}
A definition is implicitly a declaration. And a declaration must come ahead of the use.
All functions need to be declared before they are used.
You can do that by either (1) writing a declaration, or (2) writing a definition.
Relying solely on (2) can be tempting but then you are bound to order your program in a particular way, and is occasionally impossible. For example, the following will not compile unless the comment is removed.
//void bar(int);
void foo(int n)
{
if (!n){
bar(n);
}
}
void bar(int n)
if (n){
foo(n);
}
}
int main()
{
foo(1);
}
No.
If the function definition appears before the function call, then prototype is not mandatory. Otherwise function prototype is necessary to let compiler know how to respond to a function when it is called.
A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides the actual body of the function.
if the function definition appears after the function call then prototype is mandatory. because it tells the compiler to how to respond the function when it is called.
check the following example.
/* C++ Function Prototype and C++ Function Definition */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int add(int, int); // function prototype
void main()
{
clrscr();
int a, b;
cout<<"Enter any two number: ";
cin>>a>>b;
cout<<"\nSummation = "<<add(a, b);
getch();
}
int add(int x, int y) // function definition
{
int res;
res = x + y;
return res;
}
and if the function definition is made before the function call then it is not mandatory to declare function prototype.
consider example.
/* C++ Function Prototype and C++ Function Definition */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int add(int x, int y) // function definition
{
int res;
res = x + y;
return res;
}
void main()
{
clrscr();
int a, b;
cout<<"Enter any two number: ";
cin>>a>>b;
cout<<"\nSummation = "<<add(a, b);
getch();
}
This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 8 years ago.
My code is quite simple:
#include <iostream>
using namespace std;
int test(int b[]){
cout<<sizeof(b)<<endl;
return 1;
}
int main(){
int a[] ={1,2,3};
cout<<sizeof(a)<<endl;
test(a);
system("pause");
}
output of this code is:
12
4
which means that when a[] is transfered as a parameter to function test(),is has been deteriorated as a int *, so the output of size(b) is 4 ,instead of 12.So ,my question is , how can I get the actual length of b[] inside function test() ?
You could do this with a function template:
#include <cstddef> // for std::size_t
template<class T, std::size_t N>
constexpr std::size_t size(T (&)[N])
{
return N;
}
then
#include <iostream>
int main()
{
int a[] ={1,2,3};
std::cout << size(a) << std::endl;
}
Note that in C and C++, int test(int b[]) is another way of saying int test(int* b), so there is no array size information inside of the test function. Furthermore, you could use standard library container types which know their size, such as std::array.
I wrote this code:
#include <cstdlib>
#include <iostream>
#include <stdio.h>
constexpr int foo(int a, int b)
{
return a*b;
}
int bar(int a, int b)
{
return a*b;
}
int a = bar(1,2); // Dynamic initialization. This brace-or-equal initializer
// contains expression which is not a constant expression
int main()
{
a = foo(3,4); // Constexpr function invocation. Static initialization.
std::cout << a; // 12
}
This program outputs 12. I expected that 2 will be outputted. Because every Static Initialization is performed before Dynamic Initialization. I'm confused.
Assignment is not initialisation. The assignment from foo(3,4) happens after main begins (which is after the initialisation from bar(1,2)), and before printing the value.
a is not declared constexpr so it cannot be initialized via a constexpr expression. In the scenario you present, the second "initialization" is in fact a dynamic assignment.