C++ why my template expansion lead to compiler stack overflow? [duplicate] - c++

This question already has answers here:
C++11 constexpr function compiler error with ternary conditional operator (?:)
(2 answers)
Closed 6 years ago.
I was trying template meta programming and writing a function to calculate power of base^re like 3^2=9
template<int N>
int Tpow(int base){return N==0?1:base*Tpow<N-1>(base);}
int main()
{
int r3=Tpow<3>(2);
return 0;
}
Just several lines, but it crashes both gcc and clang. Where did I get wrong?
Thanks.

Solution: You have to specialize your template for N equal 0. Like:
template<>
int Tpow<0>(int base){return 1;}
Now that you have this, you could also optimize your original template like so:
template<int N>
int Tpow(int base){return base*Tpow<N-1>(base);}
because you know you handle the case of N equal 0.
Explanation: Your compiler is basically doing this: It sees
int r3=Tpow<3>(2);
and makes a function for 3 as the template variable, like so
int Tpow_3(int base){return 3==0?1:base*Tpow<3-1>(base);}
and then it needs to make a function for 2 as template variable, like so
int Tpow_2(int base){return 2==0?1:base*Tpow<2-1>(base);}
and this goes on and on an on, because the compiler doesn't care about your 0==0?... yet.

The compiler must compile the entire function body: it cannot rely on the ternary conditional to only compile one side. So there is no block on the recursion.
(Using the constexpr of C++11 will not help either).
To solve this, you need to specialise the function for the N = 0 case.

Related

How does #define work in C++ [duplicate]

This question already has answers here:
Macro Expansion
(7 answers)
The need for parentheses in macros in C [duplicate]
(8 answers)
Closed 4 years ago.
#include <iostream>
using namespace std;
#define squareOf(x) x*x
int main() {
// your code goes here
int x;
cout<<squareOf(x+4);
return 0;
}
I thought the answer would come as 16 but it came out as 4.
I am confused how does this works.
16 would never be the result here. Let's say you would have initialized x with 0, then you would have your x+4 replaced by x+4*x+4 which would evaluate as 0+4*0+4 = 4.
Preprocessor macros replace source code, they are not functions.
You might now think that maybe
#define squareOf(x) (x)*(x)
would be better, but consider that then
int x = 2;
int y = squareOf(x++);
would result in y = (2)*(3) = 6, not in 4.
If you do not have a really good reason, avoid preprocessor macros. There are good reasons, but if something behaves like a function, better make it a function.
Now take a look at this:
template <class T>
inline T squareOf(const T& number)
{
return number*number;
}
As inline, it does also replace code (at least if the compiler wants so), but here, this one actually behaves like a function (since it is one). Wouldn't expect a bad outcome from that one.

How to make the compiler aware of templated struct? [duplicate]

This question already has answers here:
Undefined reference to static variable c++
(3 answers)
Closed 6 years ago.
I am trying to implement an answer given on my question over at CodeReview.SE. Basically, I want to access some static variables in a templated struct. Consider the following example code:
#include <iostream>
using namespace std;
template<const int idx>
struct Data{
static int bar;
};
template<const int idx>
int getBar(){
return Data<idx>::bar;
}
int main() {
const int n = 2; // Arbitrary number
cout << getBar<n>();
return 0;
}
The compiler does not recognize that I want Data<n> to be available in the program - however, it recognizes the initial getBar<n> function just fine as is evident from the error message:
undefined reference to `Data<2>::bar'
How do I tell the compiler to make the templated struct available as well?
Static class variables must be given memory allocation. Add this:
template<const int idx>
int Data<idx>::bar = 0;
Demo
Edit: The dupe linked by NathanOliver hits it on the head, but for non-templated classes. This answer shows the syntax when the class is templated. minor difference, but still useful.

Why in C++ sizeof(array[]) behave in different way for bool array? [duplicate]

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 9 years ago.
Why in C++ sizeof(array) behave in different way for bool array then for arrays containing other types of data ?
Edition :
I'm asking because
sizeof(boolarray)/sizeof(boolarray[0])
don't give size of boolarray.
but this simple code prints :
4
1
////////////////////////////
#include<iostream>
using namespace std;
void printBoolArray(bool* boolarray){
cout<<sizeof(boolarray)<<"\n";
cout<<sizeof(boolarray[0]);
}
int main(){
bool boolarray[10]={false};
printBoolArray(boolarray);
}
know I understand sizeof in function which gives the size of object which makes reference, this is my 9 day with c++, sorry for stupid question, it's so obvious now
It doesn't act differently. What makes you think it does? Are you making incorrect assumptions about the size of a bool?
As has been alluded to in the comments, if you are passing an array to a function and attempting to calculate its size there, that doesn't work. You can't pass arrays to (or return them from) functions. For example:
void foo(int array[10])
{
auto size = sizeof(array);
// size == sizeof(int*), you didn't pass an array
}
#include <cstddef>
#include <iostream>
template<std::size_t n>
void printBoolArray(bool (&boolarray)[n]){
std::cout<<sizeof(boolarray)<<"\n";
std::cout<<sizeof(boolarray[0]);
}
int main(){
bool boolarray[10]={false};
printBoolArray(boolarray);
}
The above works.
sizeof(bool*) is the size of the pointer, not the array it points to.
Above, I carefully maintained the type of the boolarray. As it happens, this technique also extracts the size into the compile-time constant n.
This doesn't scale well, because when you pass arrays to functions, they rapidly decay to pointers. This is one of the reasons why std::array or std::vector can be advised -- they have fewer quirks than C style arrays.
As others have explained, arrays degenerate to pointers when passed to a function.
However, there is one work around; you can use templates.
template<typename T, size_t N>
size_t length(T (&)[N]) {
return N;
}

In a function declaration, what does passing a fixed size array signify? [duplicate]

This question already has answers here:
Why can one specify the size of an array in a function parameter?
(3 answers)
Closed 3 years ago.
This feels like a really stupid thing to ask, but I had someone taking a programming class ask me for some help on an assignment and I see this in their code (no comments on the Hungarian notation please):
void read_dictionary( string ar_dictionary[25], int & dictionary_size ) {...
Which, as mainly a C# programmer (I learned about C and C++ in college) I didn't even know you could do. I was always told, and have read since that you're supposed to have
void read_dictionary( string ar_dictionary[], int ar_dictionary_size, int & dictionary_size ) {...
I'm told that the professor gave them this and that it works, so what does declaring a fixed size array like that even mean? C++ has no native way of knowing the size of an array being passed to it (even if I think that might've been changed in the newest spec)
In a one dimensional array It has no significance and is ignored by the compiler. In a two or more dimensional array It can be useful and is used by the function as a way to determine the row length of the matrix(or multi dimensional array). for example :
int 2dArr(int arr[][10]){
return arr[1][2];
}
this function would know the address of arr[1][2] according to the specified length, and also the compiler should not accept different sizes of arrays for this function -
int arr[30][30];
2dArr(arr);
is not allowed and would be a compiler error(g++) :
error: cannot convert int (*)[30] to int (*)[10]
The 25 in the parameter declaration is ignored by the compiler. It's the same as if you'd written string ar_dictionary[]. This is because a parameter declaration of array type is implicitly adjusted to a pointer to the element's type.
So the following three function declarations are equivalent:
void read_dictionary(string ar_dictionary[25], int& dictionary_size)
void read_dictionary(string ar_dictionary[], int& dictionary_size)
void read_dictionary(string *ar_dictionary, int& dictionary_size)
Even in the case of the first function, with the size of the array explicitly declared, sizeof(ar_dictionary) will return the same value as sizeof(void*).
See this sample on Codepad:
#include <string>
#include <iostream>
using namespace std;
void read_dictionary(string ar_dictionary[25], int& dictionary_size)
{
cout << sizeof(ar_dictionary) << endl;
cout << sizeof(void*) << endl;
}
int main()
{
string test[25];
int dictionary_size = 25;
read_dictionary(test, dictionary_size);
return 0;
}
Output (the exact value is, of course, implementation-dependent; this is purely for example purposes):
4
4
I always though that passing fixed size C++ arrays was a "half baked" feature of C++. For example, ignored size matching or only being able to specify the first index size, etc... Until recently I learn this idiom:
template<size_t N1, size_t N2> // enable_if magic can be added as well
function(double(&m)[N1][N2]){
... do something with array m...knowing its size!
}
Reference: Can someone explain this template code that gives me the size of an array?

Mysterious oneliner template code, any one? [duplicate]

This question already has answers here:
Can someone explain this template code that gives me the size of an array? [duplicate]
(4 answers)
Closed 7 years ago.
I was reading this page :
C++ Tip: How To Get Array Length. The writer presented a piece of code to know the size of static arrays.
template<typename T, int size>
int GetArrLength(T(&)[size]){return size;} // what does '(&)' mean ?
.
.
.
int arr[17];
int arrSize = GetArrLength(arr); // arrSize = 17
Could anyone please shed the light on this code, because I couldn't understand how it really works.
The function is passed a reference (&) to an array of type T, and size size.
sizeof(x)/sizeof(x[0])
Won't catch errors if the array degrads to a pointer type, but it will still compile!
Templated version is bullet proof.
T(&)[size] is reference to T[size]. If you don't use reference C++ will treat T[size] as T*, and function template parameter deduction would not work.
Wow, that's tricky. I don't know either, but if you keep reading down into the comments on that page:
is essentially
int arr[17]; int arrSize =
GetArrLength(arr);
which creates this function:
int GetArrLength(int(&)[17]){return
17;}
So & must mean reference like it always does, so it's taking a reference of the array type and the size (second item in the template) is then the size of the incoming array.
Think I'll stick with old
sizeof(x)/sizeof(x[0])