Answer the question
In order to leave comments, you need to log in
C++ - how to correctly declare a constructor?
Impressed by yesterday's article about Ref-qualified ( the question is not about them, I'm just explaining what the whole garden is for ) I decided to try to do this thing:
Filling variables from a vector with the following syntax
vector<string> arr{"str1","str2","str3","str4","str5","str6"};
string a,b,c,d,e;
list(a,b,c,d,e) = arr; // в результате a == "str1", b == "str2",...
That at the same time only such syntax was possible. list q(a,b,c,d,e);
q = arr; // так нельзя
or solist q(a,b,c,d,e),w(a,b,c,d,e);
w = q; // так нельзя
In general, everything worked out. Works for any number of arguments. vector<string> arr{"str1","str2","str3","str4","str5","str6"};
string a;
list(a) = arr;
then the compiler thinks that I am re-declaring a variable a of type string as a variable of type listlist.cpp:100:8: error: conflicting declaration ‘list a’
list(a) = arr;
^
list.cpp:98:14: error: ‘a’ has a previous declaration as ‘std::string a’
std::string a,b,c,d,e;
^
and I just want to create an object by calling the constructor with one argument - the same variable a of type string. #include <iostream>
#include <vector>
struct list
{
/**
* Constructor with one argument
*/
explicit list(std::string& arg)
{
size = 1;
parr = new std::string*[1];
helper(0, arg);
}
/**
* Constructor with a variable (>1) number of arguments
* You can use any number of arguments of type std::string in the constructor.
* list(a,b,c,d) = arr;
* list(a,b) = arr;
*/
template <typename ...Args>
list(std::string& arg0, Args&... args)
{
size = sizeof...(Args)+1;
parr = new std::string*[size];
helper(0, arg0, args...);
}
/**
* Assignment operator
* Ref-qualified forbids such things:
* list c(a,b);
* c = arr;
* You can only use this form:
* list(a,b) = arr;
*/
list &operator=(std::vector<std::string> &arr) && // <-- Ref-qualified
{
unsigned int min = (size < arr.size()) ? size : arr.size();
for(unsigned int i = 0; i < min; i++)
{
*parr[i] = arr[i];
}
}
/**
* Deleted constructors. Forbids such things:
* list q(a,b,c,d,e),w(a,b,c,d,e);
* w = q;
* You can only use this form:
* list(a,b,c,d,e) = arr;
*/
list(const list &that) = delete;
list(list &&that) = delete;
list() = delete;
~list()
{
delete [] parr;
}
private:
/**
* Helper method.
* Allows to initialize the list of any number of arguments.
* Alternately, one by one makes pointers to the arguments into the internal array.
*/
template <typename ...Args>
void helper(int ind, std::string& arg0, Args&... args)
{
helper(ind, arg0);
helper(++ind, args...);
}
/**
* Helper method.
*/
void helper(int ind, std::string& arg0)
{
parr[ind] = &arg0;
}
// Internal array of pointers to pointers to arguments
std::string **parr;
// The number of arguments with which the constructor was called
unsigned int size;
};
int main(){
std::vector<std::string> arr{"str1","str2","str3","str4","str5","str6"};
std::string a,b,c,d,e;
//list(a,b,c,d,e) = arr; <-- так все работает
list(a) = arr; // <-- а так получаю error: ‘a’ has a previous declaration as ‘std::string a’
// The following code forbidden:
// list q(a,b,c,d,e);
// q = arr;
// error: passing ‘list’ as ‘this’ argument of ‘list& list::operator=(std::vector<std::string>&) &&’ discards qualifiers
// The following code forbidden:
// list q(a,b,c,d,e),w(a,b,c,d,e);
// w = q;
// error: use of deleted function ‘list& list::operator=(const list&)’
std::cout << std::endl << a << " " << b << " " << c << " " << d << " " << e << std::endl;
return 0;
};
C++11 is used, so I compiled it like this: g++ -O2 -std=c++11 list.cpp -o list
Answer the question
In order to leave comments, you need to log in
Wrap struct list in private namespace and enable copy constructor
in global namespace do like this
template <class ...Args>
_p::list list(Args&& ...args) {
return _p::list(args...);
}
Another way to show that this is a constructor call is to use the syntax with curly braces:list{a} = arr;
The function will solve all your problems.
Make a list function that will return a temporary object with an overloaded = operator, implement transfer semantics, return via std::move.
Well, the force will be with you.
And by creating an explicit object, you are making big problems for yourself.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question