I have the following code which could not be complied.
using namespace std;
void f(int);
template<typename T1, size_t N>
void array_ini_1d(T1 (&x)[N])
{
for (int i = 0; i < N; i++)
{
x[i] = 0;
}
}
What is the proper way to pass the array if the main is something like below.
int main()
{
int a;
cin >> a;
int n = a / 4;
f(n);
return 0;
}
void f(int n)
{
int arr[n];
array_ini_1d(arr);
}
error: no matching function to call to array_ini_1d..............
The problem is that variable size arrays are not supported by c++, and is only supported as compilers extension. That means, the standard doesn't say what should happen, and you should see if you can find in compiler's documentation, but I doubt that such corner cases are documented.
So, this is the problem :
int arr[n];
The solution is to avoid it, and use something supported by c++, like for example std::vector.
I don't think the compiler can deduce the size of a variable-length array in a template. Also, don't forget to forward declare f before you use it. Variable-length arrays are a GCC extension and you should get a warning regarding their use.
You may declare your function like this:
template <typename A, size_t N> void f(A a[N]) {
for(size_t i = 0; i < N; i++)
cout << a[i];
}
However, the problem is that when you call the function, the compiler won't deduce the template parameters, and you will have to specify them explicitly.
char arr[5] = {'H', 'e', 'l', 'l', 'o'};
int main()
{
//f(arr); //Won't work
f<char, sizeof(arr)/sizeof(arr[0])>(arr);
cout << endl;
return 0;
}
Unfortunately, that ruins the very idea...
UPD: And even that code does NOT work for an array that has variable length, for the length is calculated at runtime, and the template parameters are defined at compilation time.
UPD2: If using std::vector you may create it initialized:
vector<int> arr(n, 0);
Or you may fill it with fill from <algorithm> when needed:
std::fill(arr.begin(), arr.end(), 0);
As you use Variable length array (VLA) (compiler extension), compiler cannot deduce N.
You have to pass it by pointer and give the size:
template<typename T>
void array_ini_1d(T* a, std::size_t n)
{
for (std::size_t i = 0; i != n; ++i) {
a[i] = 0;
}
}
void f(int n)
{
int arr[n];
array_ini_1d(arr);
}
Or use std::vector. (no extension used so). Which seems cleaner:
template<typename T>
void array_ini_1d(std::vector<T>& v)
{
for (std::size_t i = 0, size = v.size(); i != n; ++i) {
a[i] = 0; // or other stuff.
}
}
void f(int n)
{
std::vector<int> arr(n); // or arr(n, 0).
array_ini_1d(arr);
}
Template parameters must be resolved at compile-time.
There is no way that a function template with parameter size_t N can match any sort of array or other container whose size comes from a run-time input.
You will need to provide another version of the array_1d_ini which does not have the size as a template parameter.
template<typename T, size_t N>
void f(T* a)
{
/* add your code here */
}
int main()
{
int a[10];
f<int, 10>(a);
return 0;
}
I am working on a code where an array is passed to a function by passing the pointer to the first location. In the function, part of the array is used. This creates an unsafe situation because there is a chance if the caller function does not guess the max size of the array correctly the callee function can write past the array size and a stack overflow can occur. I was thinking of a solution to this and thought of using a function template and passing the array as reference as shown in this example.
modifyArray.h
#define MAXSIZE 10
class modifyArray
{
public:
void create();
void unsafeFunction(double*);
template<int N>
void safeFunction(double (&array)[N] );
private:
int computeLength();
};
modifyArray.cpp
#include <iostream>
#include "modifyArray.h"
int modifyArray::computeLength()
{
return 11;
}
void modifyArray::create()
{
double testarray[MAXSIZE];
unsafeFunction(testarray);
safeFunction(testarray);
}
void modifyArray::unsafeFunction(double* array)
{
int operatingSize = computeLength();
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
template<int N>
void modifyArray::safeFunction(double (&array)[N] )
{
int operatingSize = computeLength();
std::cout<< "Max size" << N <<std::endl;
if(operatingSize > N) return; // Return or raise an exception
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
main.cpp
#include "modifyArray.h"
int main(int argc, const char * argv[]) {
modifyArray C;
C.create();
return 0;
}
I am looking for a solution that is minimally invasive to the existing code. Here I just have to add a template statement, change the argument from double* to reference, and insert an if statement to check the size. I don’t want to do a major rewrite. Also I don’t want to use dynamic allocation, vector, or std::array mostly because of the performance reasons. This is a low level function in a numerical simulation code and performance is very important. Is there a better solution? Is there a pitfall to doing what I am doing?
If you really want to work with raw arrays and you want to safely modify all of the elements of the array without walking of the end then you can pass the array by reference and then use a range based for loop.
tmeplate <typename T, typename Function, std::size_t N>
void do_work(T (&arr)[N], Function f)
{
for (auto & e : arr)
e = f();
}
The above will apply the result of calling function to every element of the array and is guaranteed to stay in the bounds of the array. You could use it like
int main()
{
int arr[10];
do_work(arr, []() { static int i = 0; i++; return i * i; });
for (auto e : arr)
std::cout << e << " ";
}
output:
1 4 9 16 25 36 49 64 81 100
Live Example
Is there any way to dynamically (I think that's the right term) define an int array in a class, the size of which is a private member variable in that same class? For example:
class Scene()
{
//public member functions
private:
int max;
int xcoords[max];
}
I've searched through other answered questions on here, but I haven't learned how to use vectors in class yet, which is what most responses suggest. Ideally, in my constructor for the class, I'd be passed an int max, with which I then initialize the xcoord array to have a size of max with entries all -1.
If you want dynamic sizing for your member data, you almost certainly have to store it in the heap. Which means, something like this
class Foo{
int* data;
public:
Foo(int size){
data = new int[size];
}
~Foo(){
// remember to clean up
delete[] data;
}
}
This way, your constructor will allocate size for size ints in the heap memory when the class is created, and free it up when it is deleted.
The more official c++ way of writing the constructor is:
Foo(int size):
data(new int[size])
{
}
But in the end it will do the same thing.
Consider leaving memory management to standard libraries.
Instead of Arrays, use vectors.
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::endl;
class Scene
{
public:
vector<int> verticeData;
};
int LEGACY_FUNCTION(const int * data, int count)
{
for (int i = 0; i < count; ++i)
{
cout << " ";
cout << data[i];
cout << " ";
}
cout << endl;
return 0;
}
int main()
{
Scene myscene;
myscene.verticeData.emplace_back(3);
myscene.verticeData.emplace_back(4);
myscene.verticeData.emplace_back(5);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
myscene.verticeData.clear();
myscene.verticeData.emplace_back(1);
myscene.verticeData.emplace_back(7);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
return 0;
}
I need to implement a generic algorithm that can operate on a matrix regardless of its representation. It could be a C-style 2D array, a vector of vectors or an arbitrary user class (which does not necessarily provide a subscript operator).
An obvious solution could look like this:
template<typename M>
void func(M& mat, int cols, int rows)
{
for(int j = 0; j < rows; ++j)
for(int i = 0; i < cols; ++i)
doSomething(elem(mat, i, j));
}
...where the user would have to provide an overload of 'elem' that operates on his matrix type. The problem with this approach is that this overload would need to be declared before 'func' for the code to compile, and not just before the template instantiation. Is there a way around this problem that does not involve an ugly function signature or forcing the user to write a wrapper class and other boilerplate code?
I have tried it and found a possible solution after my first comment. So Just including the declaration into the generic function, it works! See my example code below.
The point finally seems to be that the templetized code doesn't get the declaration of elem() done in the non-templetized code.
It's after the definition of the template, but before of its first instantiation, so, to my knowledge/understanding, it should be enough.... but my complier (gcc 4.8.2) complains as well. I'm sure to have used this feature many times with templetized methods and classes.
It seems really strange to me and possibly a bug (#Potatoswatter: can you give a reference to the bug - see if this match?).
EDITED: Finally understood. Still studying C++11 Stroustrup's! It works as intended in the standard. I give here some pointers - excerpts.
The first important idea is suggested in 23.3.2 (Templates, Error detection): Syntax error are checked in definitions before they are used in the first instance. Sure they are, but though that it was just defined later. But: "a name used in a template definition must either be in scope or in some reasonably obvious way depend on a template parameter". This is clear enough already now, but most important is the rationale behind this idea.
It's explained in great detail in 26.3 (Instantiation [of templates!], Name Binding): "Define template functions to minimize dependencies on nonlocal information. The reason is that a template will be used to generate functions and classes based on unknown types and in unknown contexts. Every subtle context dependency is likely to surface as a problem for somebody...".
After reading it - I'm still asking myself why I haven't thought to such an important difference, with respect to the controlled environment present within a generic class!!
Explanation go on (pages 745-758!) and the mechanism for the resolution is explained especially in 26.3.2 (Point-of-definition Binding) and 26.3.3 (Point-of-instantation Binding):
"When the compiler sees a template definition, it determines which names are dependent (26.3.1). If a name is dependent, looking for its declaration is postponed until instantiation time (26.3.3)."
"Names that do not depend on a template argument are treated like names that are not in templates; they must be in scope (6.3.4) at the point of definition".
That's stoned. elem() must be declared before it's used in the template definition - it is treated like names that are not in templates.
I agree with #Potatoswatter and others. This is probably the less elegant solution, since it restricts to the use of an external function, no functors, no lambdas.
On the other side, it addresses the problem (thought it was a workaround initially... no, it's just how it's intended to work!) of the OP.
#include <iostream>
using namespace std;
template<typename M, typename R>
void func(M mat, int cols, int rows)
{
// with this declaration it works.
R &elem(M, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
elem(mat, i, j) += 1; // +=1 is just your "doSomething()"
}
}
}
template<typename M, typename R>
void show(M mat, int cols, int rows)
{
R &elem(M, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
if (j>0) cout << ", ";
cout << elem(mat, i, j);
}
cout << endl;
}
}
float &elem(float *m, int i, int j) {
return m[i*3+j];
}
float &elem(float m[3][3], int i, int j) {
return m[i][j];
}
int main(int argc, char **argv) {
float mat1d[9] = {1,2,3,4,5,6,7,8,9};
float mat2d[3][3] = {1,2,3,4,5,6,7,8,9};
func<float*, float>(mat1d, 3, 3);
show<float*, float>(mat1d, 3, 3);
func<float(*)[3], float>(mat2d, 3, 3);
show<float(*)[3], float>(mat2d, 3, 3);
}
Trying to use references as in your question I've got slightly crazy before understanding that mixing them with statically declared sizes, let things much more stuck. I include it here because I have lost quite some time trying to get around this:
#include <iostream>
using namespace std;
template<typename M, typename R>
void func(M &mat, int cols, int rows)
{
R &elem(M&, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
elem(mat, i, j) += 1; // +=1 is just your "something"
}
}
}
template<typename M, typename R>
void show(M &mat, int cols, int rows)
{
R &elem(M&, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
if (j>0) cout << ", ";
cout << elem(mat, i, j);
}
cout << endl;
}
}
float &elem(float (&m)[9], int i, int j) {
return m[i*3+j];
}
float &elem(float (&m)[3][3], int i, int j) {
return m[i][j];
}
int main(int argc, char **argv) {
float mat1d[9] = {1,2,3,4,5,6,7,8,9};
float mat2d[3][3] = {1,2,3,4,5,6,7,8,9};
func<float[9], float>(mat1d, 3, 3);
show<float[9], float>(mat1d, 3, 3);
func<float[3][3], float>(mat2d, 3, 3);
show<float[3][3], float>(mat2d, 3, 3);
}
NOTE: in this way elem() is a function, included at link time. I think that's not what you want, but then you can get around it making a functor of all the stuff.
The easiest solution is that a subscript operator should be mandatory.
You are ok to force the user to declare a elem function, but you don't want to force him to overload a subscript operator. This doesn't make sense to me. Consider the case when he uses an array or a class that already has a subscript operator defined. Why would you force him to define a function that does what the subscript operator already does?
However this is how you do what you want:
template<typename M, typename F>
void func(M& mat, int cols, int rows, F elem)
{
for(int j = 0; j < rows; ++j)
for(int i = 0; i < cols; ++i)
doSomething(elem(mat, i, j));
}
This can be called with references to functions, pointer to functions or lambdas.
Call example with lambda:
func(mat, 5, 5, []->int (int **m, int i, int j) { return m[i][j];});
I haven't test it so I hope there are no syntax errors.
As a middle ground beside that you could have an overload what doesn't receive elem as a parameter and uses the subscript operator.
The problem with this approach is that this overload would need to be declared before 'func' for the code to compile, and not just before the template instantiation.
This sounds like a misunderstanding; it's much stronger than the actual requirement. The overload called by a particular specialization only needs to be declared before the point of instantiation of that specialization, i.e. before whatever non-template call in each translation unit that first leads to your template.
Before the template definition, you only need some function named func; it doesn't need to remotely match the call or to be useable for any purpose. It's just a placeholder to let the parser know that your template is making a function call there. This would do fine:
void elem( struct unused_tag_type ) = delete;
as would this:
void elem();
Below is my attempt towards a minimal running sample to demonstrate the problem, and a solution. I have only been able to produce the problem when functions and data are defined in different namespaces. I think this is the most general case.
Problem (live example):
namespace X { struct A {}; }
namespace Y { // function-style
template<typename T>
void f(T x) { h(x); }
void g() { f(X::A{}); }
void h(X::A) { cout << "Hello, world!" << endl; }
}
Solution (live example):
namespace X { struct A {}; }
namespace Y { // functor-style
template<typename T>
struct H;
template <typename T>
void h(T x) { H<T>()(x); }
template<typename T>
void f(T x) { h(x); }
void g() { f(X::A{}); }
template<>
struct H<X::A>
{
void operator()(X::A) { cout << "Hello, world!" << endl; }
};
}
In words, use a template struct (function object, H) to do the job and a template function (h) only as a wrapper. H can be specialized whenever you like (but in the same namespace). Its general declaration and the declaration of h should appear before the point of instantiation in g().
Limitation (live example): Unfortunately, this does not work if the return type is unknown, that is, if you replace H and h by the most general forms
template<typename... T>
struct H;
template <typename... T>
auto h(T&&... x)
->decltype(H<T...>()(std::forward <T>(x)...))
{ return H<T...>()(std::forward <T>(x)...); }
I've tried and it doens't even work with -std=c++1y without the training return type. But I hope this is not an issue in your case.
I have the following code which could not be complied.
using namespace std;
void f(int);
template<typename T1, size_t N>
void array_ini_1d(T1 (&x)[N])
{
for (int i = 0; i < N; i++)
{
x[i] = 0;
}
}
What is the proper way to pass the array if the main is something like below.
int main()
{
int a;
cin >> a;
int n = a / 4;
f(n);
return 0;
}
void f(int n)
{
int arr[n];
array_ini_1d(arr);
}
error: no matching function to call to array_ini_1d..............
The problem is that variable size arrays are not supported by c++, and is only supported as compilers extension. That means, the standard doesn't say what should happen, and you should see if you can find in compiler's documentation, but I doubt that such corner cases are documented.
So, this is the problem :
int arr[n];
The solution is to avoid it, and use something supported by c++, like for example std::vector.
I don't think the compiler can deduce the size of a variable-length array in a template. Also, don't forget to forward declare f before you use it. Variable-length arrays are a GCC extension and you should get a warning regarding their use.
You may declare your function like this:
template <typename A, size_t N> void f(A a[N]) {
for(size_t i = 0; i < N; i++)
cout << a[i];
}
However, the problem is that when you call the function, the compiler won't deduce the template parameters, and you will have to specify them explicitly.
char arr[5] = {'H', 'e', 'l', 'l', 'o'};
int main()
{
//f(arr); //Won't work
f<char, sizeof(arr)/sizeof(arr[0])>(arr);
cout << endl;
return 0;
}
Unfortunately, that ruins the very idea...
UPD: And even that code does NOT work for an array that has variable length, for the length is calculated at runtime, and the template parameters are defined at compilation time.
UPD2: If using std::vector you may create it initialized:
vector<int> arr(n, 0);
Or you may fill it with fill from <algorithm> when needed:
std::fill(arr.begin(), arr.end(), 0);
As you use Variable length array (VLA) (compiler extension), compiler cannot deduce N.
You have to pass it by pointer and give the size:
template<typename T>
void array_ini_1d(T* a, std::size_t n)
{
for (std::size_t i = 0; i != n; ++i) {
a[i] = 0;
}
}
void f(int n)
{
int arr[n];
array_ini_1d(arr);
}
Or use std::vector. (no extension used so). Which seems cleaner:
template<typename T>
void array_ini_1d(std::vector<T>& v)
{
for (std::size_t i = 0, size = v.size(); i != n; ++i) {
a[i] = 0; // or other stuff.
}
}
void f(int n)
{
std::vector<int> arr(n); // or arr(n, 0).
array_ini_1d(arr);
}
Template parameters must be resolved at compile-time.
There is no way that a function template with parameter size_t N can match any sort of array or other container whose size comes from a run-time input.
You will need to provide another version of the array_1d_ini which does not have the size as a template parameter.
template<typename T, size_t N>
void f(T* a)
{
/* add your code here */
}
int main()
{
int a[10];
f<int, 10>(a);
return 0;
}