struct M{
T opIndex(uint i){ ... }
}
which gives me this:
m[i]
but what if I want it in two dimension so that I could do:
m[i][j]
is there anyway to do this?
Yes, you can do the C++ way of returning a temporary object (struct is best in D's case) which also has an index operator overload.
But a better idea in D is to go for the syntax m[i, j]:
struct S
{
uint opIndex(uint i, uint j)
{
return i + j;
}
}
void main()
{
S s;
assert(s[2, 3] == 5);
}
If you still want to use m[i][j], a nested struct gives you some syntactic leeway:
struct S
{
auto opIndex(uint i)
{
struct Temp
{
uint opIndex(uint j)
{
return i + j;
}
}
return Temp();
}
}
void main()
{
S s;
assert(s[2][3] == 5);
}
Related
std::vector<std::string> get() {
std::vector<string> result {};
for (int i = 0; i < 10000) {
result.emplace_back("test" + to_string(i));
}
return result;
}
//or
void get(std::vector<std::string>& result) {
for (int i = 0; i < 10000) {
result.emplace_back("test" + to_string(i));
}
}
//Is it more efficient to go through the reference than to return it? Or is copying elision and is it the same in terms of efficiency?
int main()
{
auto arr = get();
std::vector<std::string> arrPassingByRef{};
get(arrPassingByRef);
}
The goal I set to myself is to overload operator+ (adding class objects). It turns out that this sum can be just interpreted as the sum of two vectors. But when it comes to the method operator+, I find it difficult to return the object. I've read similar topics and even try to apply some sugestions but with no success, unfortunatelly. I enclose some of my code.
template<class Y>
class myVect {
public:
myVect(int n = 1);
~myVect();
myVect(const myVect& a);
myVect& operator= (const myVect&);
myVect& operator+ (const myVect&);
void display(const myVect& a);
private:
int size;
Y* data;
template<class U> friend class myClass;
};
template<class Y> // constructor
myVect<Y>::myVect(int n) {
size = n;
data = new Y[size];
cout << endl << "Pass the elements" << " " << size << "\n";
for (int i = 0; i < size; i++) {
cin >> *(data + i);
}
}
template <class Y> // deconstructor
myVect<Y> :: ~myVect() {
delete[] data;
}
template<class Y> // copy constructor
myVect<Y> ::myVect(const myVect & a) {
size = a.size;
data = new Y[size];
for (int i = 0; i < size; i++) {
*(data + i) = *(a.data + i);
}
}
template<class Y> //ASSIGMENT OPERATOR
myVect<Y> & myVect<Y> :: operator= (const myVect<Y> & a) {
if (this != &a) {
delete[] data;
size = a.size;
data = new Y[size];
for (int i = 0; i < size; i++) {
*(data + i) = *(a.data + i);
}
}
return *this;
}
The method operator+ is a follows:
template<class Y>
myVect<Y>& myVect<Y> ::operator+ (const myVect<Y>& a) {
if (this->size != a.size) {
cout << endl << "not able to perform that operation - wrong dimensions" << endl;
}
else {
myVect<Y> newObj(this->size);
for (int i = 0; i < this->size; i++) {
*(newObj.data + i) = *(this->data + i) + *(a.data + i);
}
}
return newObj;
}
The error I get is 'newObj': identifier not found. I believe it's due to deconstructor. I tried to put the class myVect into a new class (encapsulate it) and contruct the return method but it didn't change antything - the type of the error is still the same. Do you know how to solve this problem?
Anyway, if it is the destructor fault, does that mean that newObj is deleted before its return?
The problem can be reduced to this:
int foo()
{
if (true) // In reality, some meaningful condition
{
int x = 4;
}
return x;
}
The variable is scoped to the if block. It doesn't exist outside of it.
You'll have to move its declaration out of the conditional, and do whatever else is required to make that work… or return from inside the condition, and do something else (throw an exception?) otherwise.
For example, given the above demonstration:
int foo()
{
int x = 0; // Or some other value
if (true) // In reality, some meaningful condition
{
x = 4;
}
return x;
}
or:
int foo()
{
if (true) // In reality, some meaningful condition
{
int x = 4;
return x;
}
throw std::runtime_error("For some reason I have no value to give you!");
}
Your next problem will be that you are trying to return a local variable by reference. You cannot do that. Return it by value instead, which is anyway idiomatic for what you're doing.
You've declared your object inside of a block, so it won't exist in the outside scope. This would normally free you up to reuse variable names across different branches; try making a newObj inside the if part of the statement and watch it not throw an error, for example.
Yesterday my friend challenged me to write a function in C which would return an array of function pointers where i-th function would return i.
It is easy to get a similar effect in C++, but I am not sure how to do it in C.
Can anyone help me with that?
Edit.
The effect that I am looking for is something equivalent to this.
vector <function<int()>> get_functions(int n) {
vector <function<int()>> functions;
for (int i = 0; i < n; ++i) {
functions.emplace_back([i]() {
return i;
});
}
return functions;
}
int main() {
auto functions = get_functions(10);
for (auto f:functions) {
cout << f() << endl;
}
return 0;
}
Edit.
As asked in the comment section I provide my poor attempt on the challenge.
typedef int (*fun_t)(void);
int fun() { return 0; }
int fun1() { return 1; }
fun_t *get_functions() {
fun_t *functions = malloc(sizeof(fun_t) * 2);
functions[0] = fun;
functions[1] = fun1;
return functions;
}
int main() {
fun_t* funs=get_functions();
for (int i = 0; i < 2; ++i) {
printf("%d\n",funs[i]());
}
free(funs);
}
The C++ code is cheating. function<int()> is not a function pointer; in fact, it's not a pointer at all, it's a class.
Therefore the equivalent C code would look something like this:
#include <stdio.h>
#include <stdlib.h>
// function<int ()>, simplified version just for this task
typedef struct {
int (*code)(int);
int ctx;
} function_int_t;
// function<int()>::operator()()
int call(function_int_t fun) {
return fun.code(fun.ctx);
}
// lambda body
int proto(int ctx) {
return ctx;
}
function_int_t *get_functions(size_t n) {
function_int_t *functions = calloc(n, sizeof *functions);
if (!functions) {
abort(); // hey, that's how C++ does it
}
for (size_t i = 0; i < n; i++) {
functions[i] = (function_int_t){ proto, i }; // capture i
}
return functions;
}
int main(void) {
size_t n = 10;
function_int_t *functions = get_functions(n);
for (size_t i = 0; i < n; i++) {
printf("%d\n", call(functions[i]));
}
free(functions);
return 0;
}
I'm working on a c++ project and I have a case as below:
void func(int a, int b)
{
if (some_bool)
{
generateString(generateFunc()); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = generateInt2(); // different
}
}
}
}
void func(int a, int b, string str)
{
if (some_bool)
{
generateString(generateFunc(str)); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = convertStrToInt(str); //different
}
}
}
}
As you see, I have two overloading functions.
Their logical structures are the same but some details are not.
I'm considering if there is some technique which can merge them so that I can have a better design. Because for now I have to change two times if I need to do some change.
You can use templates and do something like this:
template<typename F, typename... A>
void func(int a, int b, F &&f, A&&... a)
{
if (some_bool)
{
generateString(generateFunc(std::forward<A>(a)...)); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = std::forward<F>(f)(std::forward<A>(a)...); //different
}
}
}
}
Then call your function as it follows:
func(0, 0, generateInt2);
// or
func(0, 0, convertStrToInt, std::string{0});
I am trying to create a method that creates an array of double the size given, then fills the first half of the array with the original values and the second half with the original values in reverse order. I have completed this but the next task is to make the method accept arrays of generic type and i'm stuck and not sure where to go from here
my code so far:
template <typename T>
T& *copy_and_reverse(T& *a, int length) {
T& *result = new T&[length*2];
int w = length-1;
for (int i = 0; i < length * 2; i++) {
if (i < length) {
result[i] = a[i];
} else {
result[i]=a[w];
w--;
}
}
return result;
}
int main() {
double numbers[5]={8.364,4.3,5.3,9.6,7.645};
int size=sizeof numbers/sizeof(double);
double *pointertonumbers;
pointertonumbers=copy_and_reverse(numbers, size);
for(int i=0;i<size*2;i++){
cout<<pointertonumbers[i]<<"\n";
}
}
at the moment the code does not work as i get multiple "error: cannot declare pointer to 'T&'"
If the compilre says that it cannot declare pointer to T& then try to declare a reference to T *. Maybe the compiler will be happy in this case.:)
T * copy_and_reverse( const T *a, int length) {
T *result = new T[length*2];
As for me I would use standard algorithm std::copy. For example
template <typename T>
T * copy_and_reverse( const T *a, size_t length)
{
T *result = new T[ 2 * length ];
std::copy( a, a + length, result );
std::copy( a, a + length, reverse_iterator<int *>( result + 2 * length ) );
return result;
}
First, you cannot create pointer to reference (what you are trying to do). Reference to a pointer would be T* &a. And you should not return pointer to a reference (and reference to a pointer either, as it will create dangling reference)
Actually, it's better to be on a safe side and accept a reference to an array.
T* copy_and_reverse(T (&a) [N]) {
T *result = new T[N*2];
size_t w = N-1;
for (size_t i = 0; i < N * 2; i++) {
if (i < N) {
result[i] = a[i];
} else {
result[i]=a[w];
w--;
}
}
return result;
}
int main() {
double numbers[5]={8.364,4.3,5.3,9.6,7.645};
int size=sizeof numbers/sizeof(double);
double *pointertonumbers;
pointertonumbers=copy_and_reverse(numbers);
for(int i=0;i<size*2;i++){
std::cout<<pointertonumbers[i]<<"\n";
}
delete [] pointertonumbers;
}
This still have issues. You should not forget to delete result of a function. With C++11 you can rewrite it really safe with std::arrays:
std::array<T, N*2> copy_and_reverse(const std::array<T, N>& orig) {
std::array<T, N*2> result;
std::copy(orig.begin(), orig.end(), result.begin());
std::copy(orig.begin(), orig.end(), std::reverse_iterator<typename std::array<T, N*2>::iterator>(result.end()));
return std::move(result);
}
int main() {
std::array<double, 5> numbers = {{8.364,4.3,5.3,9.6,7.645}};
auto pointertonumbers(copy_and_reverse(numbers));
for(size_t i=0;i<pointertonumbers.size();i++){
std::cout<<pointertonumbers[i]<<"\n";
}
}
Here you get rid of pointers (and all its issues) completely.