Variable array dimension at runtime C++ - c++

I'm trying to create a program that can read some data from 2 files.
The first file is the header, that describe the data structure (dimensions, data type, extents, etc...), and the second is the raw data.
To handle different data type at runtime, I created a templated class that will be used as a container for the data. Depending on the data type read in the header, I will create a specialized class of the container to store the data.
However, now I'm facing another issue. How can I create a dynamic multidimensional array at runtime ?
I first thought doing it the old fashion way, and put a pointer into the storage class, and creating some loops ( = to the dimensionality) to create a new array (new array[size]).
But I don't think it's a very clean way of doing it.
I also thought about stacking std::vector, but I don't know the dimensionnality before runtime.
Then I considered using boost to create a multi_array, and using resize() to update the extent of my array at runtime, but it is required to know the dimension when creating the array (multi_array< type, dim > variable).
As I want to be able to access this in all my class (for future processing, etc...), I don't see how to put that in my class, as I will only know the dimensionnality at runtime.
Is it possible to create a base pointer of multi_array in my class, and declare it later (when I will know the dimension needed) ?
Or is there another way to do this ?
My final goal is to create a multidimensional array at runtime, that I can access in all my class.
Thank you.
Edit: Most of the topics I read about it are for fixed dimensional array, with a variating size. But in my case, dimension also varies.
Update: Your answer inspired me an idea Hugues.
I already have a templated class to read the data, but for now it only takes as parameter, the data type.
I'm thinking adding the dimensionnality to it and create a class like that:
storageClass< data_type, data_dimension > myStorage(filename, data_extent, data_endian, data_encoding);
This way, I can also template the dimensionnality of the data, and create a multidimensionnal array (using boost for example).
I will let you know if it worked.
Thank you.
Update 2: Apparently it's not possible cause templates expect constant expression. I cannot pass the variable 'dimension' (even if it's a fixed value in this case, but it's not define at compile-time).
So I guess my best option is to create a variadic getter in the custom storage class, and return the corresponding value. The problem is that a variadic method involve to parse the arguments, and as this is a method that will be frequently called, it's not optimal.

It is likely necessary to create a custom class.
One idea is to have it contain two main members m_dims and m_data:
#include <vector>
#include <cassert>
using std::size_t;
template<typename T> class MultiArray {
public:
MultiArray(const std::vector<int>& dims)
: m_dims(dims), m_data(product(m_dims)) { }
const std::vector<int>& dims() const { return m_dims; }
const T& operator[](const std::vector<int>& indices) const {
return m_data[index(indices)];
}
T& operator[](const std::vector<int>& indices) {
return m_data[index(indices)];
}
private:
std::vector<int> m_dims;
std::vector<T> m_data;
static size_t product(const std::vector<int>& dims) {
size_t result = 1;
for (size_t i = 0; i<dims.size(); ++i) result *= size_t(dims[i]);
return result;
}
size_t index(const std::vector<int>& indices) const {
size_t v = 0;
for (size_t i = 0; i<m_dims.size(); ++i) {
assert(indices[i]>=0 && indices[i]<m_dims[i]);
if (i) v *= size_t(m_dims[i]);
v += size_t(indices[i]);
}
return v;
}
};
int main() {
MultiArray<float> ar{std::vector<int>{2, 3}};
ar[std::vector<int>{0, 0}] = 1.f;
ar[std::vector<int>{0, 1}] = 2.f;
ar[std::vector<int>{0, 2}] = 3.f;
ar[std::vector<int>{1, 0}] = 4.f;
ar[std::vector<int>{1, 1}] = 5.f;
ar[std::vector<int>{1, 2}] = 6.f;
}
See code in http://coliru.stacked-crooked.com/a/92e597d4769f9cad

Related

Known array / pointer size as argument

InputManager* input = new InputManager(new int[]{ SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT });
I wanna pass this array of keys (or a pointer to it) but i need the InputManager's constructor to know its size. Since its known at compile time how would i get it?
Online i found this template
template <int N>
InputManager::InputManager(int (&keyArray)[N]) {
this->maxKeys = N;
this->keys = keyArray;
}
But i get an error that the arguments dont match.
I need any possible solution where i dont need to manually write the length. So macros, templates or anything else is accepted.
Don't use so many pointers. It's not healthy and you're likely to either leak memory, or try to free memory that you can't (if you didn't pass a newly-allocated array). Here's a minimal modification of your code:
class InputManager {
public:
template <int N>
InputManager(int (&keyArray)[N])
: maxKeys(N), keys(std::make_unique<int[]>(N))
{
std::copy_n(keyArray, N, keys.get());
}
private:
std::size_t maxKeys;
std::unique_ptr<int[]> keys;
};
int main() {
int keys[] = { 1, 5, 4, 7, 2 };
InputManager input {keys};
}
This compiles (GodBolt).
Notes:
This way, you don't need to write a custom destructor; although you would need to write an assignment operator which copies data; and a copy constructor.
It's probably better to just use an std::vector internally (or std::array if you know the input size beforehand), and take any span or range of keys in the constructor.
Wrap creating of this array into function using variadic template.
If you want only return a pointer to array:
template<class ... enums>
int* makeArray (enums ... e) {
return new int[sizeof...(e)]{e...};
}
When you want to know size of returned array you can return pair:
template<class ... enums>
std::pair< int*, size_t > makeArray2(enums ... e) {
constexpr size_t N = sizeof...(e);
return std::make_pair( new int[N]{e...}, N);
}

Save reference to void pointer in a vector during loop iteration

Guys I have a function like this (this is given and should not be modified).
void readData(int &ID, void*&data, bool &mybool) {
if(mybool)
{
std::string a = "bla";
std::string* ptrToString = &a;
data = ptrToString;
}
else
{
int b = 9;
int* ptrToint = &b;
data = ptrToint;
}
}
So I want to use this function in a loop and save the returned function parameters in a vector (for each iteration).
To do so, I wrote the following struct:
template<typename T>
struct dataStruct {
int id;
T** data; //I first has void** data, but would not be better to
// have the type? instead of converting myData back
// to void* ?
bool mybool;
};
my main.cpp then look like this:
int main()
{
void* myData = nullptr;
std::vector<dataStruct> vec; // this line also doesn't compile. it need the typename
bool bb = false;
for(int id = 1 ; id < 5; id++) {
if (id%2) { bb = true; }
readData(id, myData, bb); //after this line myData point to a string
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
}
}
Or is there a better way to do that without template? I used c++11 (I can't use c++14)
The function that you say cannot be modified, i.e. readData() is the one that should alert you!
It causes Undefined Behavior, since the pointers are set to local variables, which means that when the function terminates, then these pointers will be dangling pointers.
Let us leave aside the shenanigans of the readData function for now under the assumption that it was just for the sake of the example (and does not produce UB in your real use case).
You cannot directly store values with different (static) types in a std::vector. Notably, dataStruct<int> and dataStruct<std::string> are completely unrelated types, you cannot store them in the same vector as-is.
Your problem boils down to "I have data that is given to me in a type-unsafe manner and want to eventually get type-safe access to it". The solution to this is to create a data structure that your type-unsafe data is parsed into. For example, it seems that you inteded for your example data to have structure in the sense that there are pairs of int and std::string (note that your id%2 is not doing that because the else is missing and the bool is never set to false again, but I guess you wanted it to alternate).
So let's turn that bunch of void* into structured data:
std::pair<int, std::string> readPair(int pairIndex)
{
void* ptr;
std::pair<int, std::string> ret;
// Copying data here.
readData(2 * pairIndex + 1, ptr, false);
ret.first = *reinterpret_cast<int*>(ptr);
readData(2 * pairIndex + 2, ptr, true);
ret.second = *reinterpret_cast<std::string*>(ptr);
}
void main()
{
std::vector<std::pair<int, std::string>> parsedData;
parsedData.push_back(readPair(0));
parsedData.push_back(readPair(1));
}
Demo
(I removed the references from the readData() signature for brevity - you get the same effect by storing the temporary expressions in variables.)
Generally speaking: Whatever relation between id and the expected data type is should just be turned into the data structure - otherwise you can only reason about the type of your data entries when you know both the current ID and this relation, which is exactly something you should encapsulate in a data structure.
Your readData isn't a useful function. Any attempt at using what it produces gives undefined behavior.
Yes, it's possible to do roughly what you're asking for without a template. To do it meaningfully, you have a couple of choices. The "old school" way would be to store the data in a tagged union:
struct tagged_data {
enum { T_INT, T_STR } tag;
union {
int x;
char *y;
} data;
};
This lets you store either a string or an int, and you set the tag to tell you which one a particular tagged_data item contains. Then (crucially) when you store a string into it, you dynamically allocate the data it points at, so it will remain valid until you explicitly free the data.
Unfortunately, (at least if memory serves) C++11 doesn't support storing non-POD types in a union, so if you went this route, you'd have to use a char * as above, not an actual std::string.
One way to remove (most of) those limitations is to use an inheritance-based model:
class Data {
public:
virtual ~Data() { }
};
class StringData : public Data {
std::string content;
public:
StringData(std::string const &init) : content(init) {}
};
class IntData : public Data {
int content;
public:
IntData(std::string const &init) : content(init) {}
};
This is somewhat incomplete, but I think probably enough to give the general idea--you'd have an array (or vector) of pointers to the base class. To insert data, you'd create a StringData or IntData object (allocating it dynamically) and then store its address into the collection of Data *. When you need to get one back, you use dynamic_cast (among other things) to figure out which one it started as, and get back to that type safely. All somewhat ugly, but it does work.
Even with C++11, you can use a template-based solution. For example, Boost::variant, can do this job quite nicely. This will provide an overloaded constructor and value semantics, so you could do something like:
boost::variant<int, std::string> some_object("input string");
In other words, it's pretty what you'd get if you spent the time and effort necessary to finish the inheritance-based code outlined above--except that it's dramatically cleaner, since it gets rid of the requirement to store a pointer to the base class, use dynamic_cast to retrieve an object of the correct type, and so on. In short, it's the right solution to the problem (until/unless you can upgrade to a newer compiler, and use std::variant instead).
Apart from the problem in given code described in comments/replies.
I am trying to answer your question
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
Before that you need to modify vec definition as following
vector<dataStruct<void>> vec;
Now you can simple push element in vector
vec.push_back({id, &mydata, bb});
i have tried to modify your code so that it can work
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
struct dataStruct
{
int id;
T** data;
bool mybool;
};
void readData(int &ID, void*& data, bool& mybool)
{
if (mybool)
{
data = new string("bla");
}
else
{
int b = 0;
data = &b;
}
}
int main ()
{
void* mydata = nullptr;
vector<dataStruct<void>> vec;
bool bb = false;
for (int id = 0; id < 5; id++)
{
if (id%2) bb = true;
readData(id, mydata, bb);
vec.push_back({id, &mydata, bb});
}
}

vector of variable type vectors

I am currently implementing a data storage for a large table in C++. The table needs to be able to store different data type for each of a variable number of columns.
The type and the length of each column are defined and run-time. Because of this, I figured, a vector of pointer to vectors would be the right approach. I can however not figure out how to do this with variable data types.
I looked at How to get a vector of different vectors in C++ but there is not dynamic solution.
I am open to any other solutions, I don't necessarily need vectors, but the table should be re-sizable at run-time.
It should look something like this:
0 1 2 3 ...
- - - - -
1 a 0 1.3 ...
2 b 1 2.5 ...
3 c 0 1.5 ...
4 d 0 0.8 ...
5 e 1 1.2 ...
.. .. .. ... ...
I some people have suggested using boost::any but I am a bit reluctant of this (in terms of efficiency) because the table has to load large packet files from disk.
The any Class implemented in boost will do what you need.
Here is an example how to use it from their website:
#include <vector>
#include <boost/any.hpp>
using boost::any_cast;
typedef std::vector<boost::any> many;
void append_int(many & values, int value)
{
boost::any to_append = value;
values.push_back(to_append);
}
void append_string(many & values, const std::string & value)
{
values.push_back(value);
}
void append_char_ptr(many & values, const char * value)
{
values.push_back(value);
}
void append_any(many & values, const boost::any & value)
{
values.push_back(value);
}
void append_nothing(many & values)
{
values.push_back(boost::any());
}
If you cannot use boost and do not want to re-implement boost::any you could use void * as the poor man's any container. The table level would be a std::vector<void *> and each column (of type T) would be a std::vector<T>. You then allocate each column in turn and store the address of the column in the initial std::vector<void *>.
Provided you cast the value of each column before using it it should work. Depending on your requirements it may be more or less simple to implement that correctly because as you have raw pointers you should implement carefully the destructors and if appropriate copy an move constructors and assignements or declare them deleted. But it is a (poor man's) boost alternative...
To store different types in vector is impossible, but if you store pointers without type (void*), then you can retype it to any type you want. If you don't know at runtime what type you are reading, then make struct containing pointer void* and variable to determine type.
It's while since I used C++ so example can be just pseudo C++.
#include<vector>
#include<iostream>
void workWithCharArray(char* c);
typedef struct mytype {
int type = 0; // this defining default values is available since C++11
void* var = nullptr;
} Mytype;
int main() {
char* ptr = (char*)"Testing string";
std::vector<Mytype> container;
Mytype tostore;
tostore.type = 1;
tostore.var = (void*)ptr;
container.append(tostore);
switch (tostore.type) {
case 1:
workWithCharArray((char*)tostore.var);
break;
default:
std::cerr << "Unknown type - Error handling";
}
return 0;
}
void workWithCharArray(char* c) {
std::cout << c << std::endl;
}
If you need a two-dimensional vector that stores one-dimensional vectors of different data types, you could create an abstract, non-templated base class for the inner vector and then store pointers to that abstract base class in the outer vector, utilising polymorphism if you want to call member functions on the abstract vectors.
class AbstractVector {
... // provide pure virtual interface here
}
template<class T>
class MyVector : public AbstractVector, public std::vector<T> {
... /* provide implementation of pure virtual interface using
already available functionality from std::vector here */
}
In your implementation you can then store pointers to the base class AbstractVector (or unique_ptrs or shared_ptrs depending on what you want to do):
std::vector<AbstractVector *> table;
MyVector<int> * columnOne = new MyVector<int>;
MyVector<float> * columnTwo = new MyVector<float>;
table.push_back(columnOne);
table.push_back(columnTwo);

Calling templated function with type unknown until runtime

I have a this function to read 1d arrays from an unformatted fortran file:
template <typename T>
void Read1DArray(T* arr)
{
unsigned pre, post;
file.read((char*)&pre, PREPOST_DATA);
for(unsigned n = 0; n < (pre/sizeof(T)); n++)
file.read((char*)&arr[n], sizeof(T));
file.read((char*)&post, PREPOST_DATA);
if(pre!=post)
std::cout << "Failed read fortran 1d array."<< std::endl;
}
I call this like so:
float* new_array = new float[sizeof_fortran_array];
Read1DArray(new_array);
Assume Read1DArray is part of a class, which contains an ifstream named 'file', and sizeof_fortran_array is already known. (And for those not quite so familiar with fortran unformatted writes, the 'pre' data indicates how long the array is in bytes, and the 'post' data is the same)
My issue is that I have a scenario where I may want to call this function with either a float* or a double*, but this will not be known until runtime.
Currently what I do is simply have a flag for which data type to read, and when reading the array I duplicate the code something like this, where datatype is a string set at runtime:
if(datatype=="float")
Read1DArray(my_float_ptr);
else
Read1DArray(my_double_ptr);
Can someone suggest a method of rewriting this so that I dont have to duplicate the function call with the two types? These are the only two types it would be necessary to call it with, but I have to call it a fair few times and I would rather not have this duplication all over the place.
Thanks
EDIT:
In response to the suggestion to wrap it in a call_any_of function, this wouldnt be enough because at times I do things like this:
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_stuff(my_double_ptr);
}
// More stuff happening in between
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_different_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_different_stuff(my_double_ptr);
}
If you think about the title you will realize that there is a contradiction in that the template instantiation is performed at compile time but you want to dispatch based on information available only at runtime. At runtime you cannot instantiate a template, so that is impossible.
The approach you have taken is actually the right one: instantiate both options at compile time, and decide which one to use at runtime with the available information. That being said you might want to think your design.
I imagine that not only reading but also processing will be different based on that runtime value, so you might want to bind all the processing in a (possibly template) function for each one of the types and move the if further up the call hierarchy.
Another approach to avoid having to dispatch based on type to different instantiations of the template would be to loose some of the type safety and implement a single function that takes a void* to the allocated memory and a size argument with the size of the type in the array. Note that this will be more fragile, and it does not solve the overall problem of having to act on the different arrays after the data is read, so I would not suggest following this path.
Because you don't know which code path to take until runtime, you'll need to set up some kind of dynamic dispatch. Your current solution does this using an if-else which must be copied and pasted everywhere it is used.
An improvement would be to generate a function that performs the dispatch. One way to achieve this is by wrapping each code path in a member function template, and using an array of member function pointers that point to specialisations of that member function template. [Note: This is functionally equivalent to dynamic dispatch using virtual functions.]
class MyClass
{
public:
template <typename T>
T* AllocateAndRead1DArray(int sizeof_fortran_array)
{
T* ptr = new T[sizeof_fortran_array];
Read1DArray(ptr);
return ptr;
}
template <typename T>
void Read1DArrayAndDoStuff(int sizeof_fortran_array)
{
Do_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
template <typename T>
void Read1DArrayAndDoOtherStuff(int sizeof_fortran_array)
{
Do_different_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
// map a datatype to a member function that takes an integer parameter
typedef std::pair<std::string, void(MyClass::*)(int)> Action;
static const int DATATYPE_COUNT = 2;
// find the action to perform for the given datatype
void Dispatch(const Action* actions, const std::string& datatype, int size)
{
for(const Action* i = actions; i != actions + DATATYPE_COUNT; ++i)
{
if((*i).first == datatype)
{
// perform the action for the given size
return (this->*(*i).second)(size);
}
}
}
};
// map each datatype to an instantiation of Read1DArrayAndDoStuff
MyClass::Action ReadArrayAndDoStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoStuff<double>),
};
// map each datatype to an instantiation of Read1DArrayAndDoOtherStuff
MyClass::Action ReadArrayAndDoOtherStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoOtherStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoOtherStuff<double>),
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch(ReadArrayAndDoStuffMap, "float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch(ReadArrayAndDoOtherStuffMap, "double", 542);
}
If performance is important, and the possible set of types is known at compile time, there are a few further optimisations that could be performed:
Change the string to an enumeration that represents all the possible data types and index the array of actions by that enumeration.
Give the Dispatch function template parameters that allow it to generate a switch statement to call the appropriate function.
For example, this can be inlined by the compiler to produce code that is (generally) more optimal than both the above example and the original if-else version in your question.
class MyClass
{
public:
enum DataType
{
DATATYPE_FLOAT,
DATATYPE_DOUBLE,
DATATYPE_COUNT
};
static MyClass::DataType getDataType(const std::string& datatype)
{
if(datatype == "float")
{
return MyClass::DATATYPE_FLOAT;
}
return MyClass::DATATYPE_DOUBLE;
}
// find the action to perform for the given datatype
template<typename Actions>
void Dispatch(const std::string& datatype, int size)
{
switch(getDataType(datatype))
{
case DATATYPE_FLOAT: return Actions::FloatAction::apply(*this, size);
case DATATYPE_DOUBLE: return Actions::DoubleAction::apply(*this, size);
}
}
};
template<void(MyClass::*member)(int)>
struct Action
{
static void apply(MyClass& object, int size)
{
(object.*member)(size);
}
};
struct ReadArrayAndDoStuff
{
typedef Action<&MyClass::Read1DArrayAndDoStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoStuff<double>> DoubleAction;
};
struct ReadArrayAndDoOtherStuff
{
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<double>> DoubleAction;
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch<ReadArrayAndDoStuff>("float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch<ReadArrayAndDoOtherStuff>("double", 542);
}

optimize output value using a class and public member

Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.