11

I am using MinGW-w64 with 4.8.1 (with -std=c++11) and trying to call one constructor of my class within another constructor of the same class. Unfortunately, I failed to compile the code below.

A::A(const char *pc) {
  A(string(pc));
}

A::A(string s) {
  vector<string> tmpVector;
  tmpVector.push_back(s);
  A(tmpVector);
}

// Constructor
A::A(vector<string> filePathVector) {
}

Below is the error GCC is complaining about.

In file included from ../parser/nsn/parser.h:37:0,
             from main.cpp:2:
../parser/nsn/parserimp.h: In constructor 'A::A(std::string)':
../parser/nsn/parserimp.h:522:29: error: conflicting declaration 'A  tmpVector'
  A(tmpVector);
                         ^
 ../parser/nsn/parserimp.h:520:17: error: 'tmpVector' has a previous declaration as   'std::vector<std::basic_string<char> > tmpVector'
  vector<string> tmpVector;

I've read about delegated constructor concept in C++11 but I am not sure this is what I am after....

fnisi
  • 1,181
  • 1
  • 14
  • 24

2 Answers2

27

This

A(tmpVector);

is the same as this

A tmpVector; // but there is already an object called tmpVector

This explains the error. It looks like you want to call another constructor to initialize the same object. In this case you can use delegating constructors:

A::A(string s) : A(vector<string>{s})
{
}

Note that this was one of the latest C++11 language features to be added to the most popular compilers, so it may not work if your compiler doesn't have full C++11 language support.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • How is `A(tmpVector);` the same as `A tmpVector;`? – Remy Lebeau Jun 11 '14 at 05:29
  • @RemyLebeau In this context, the `()` are superfluous. See [this example](http://ideone.com/6FXEZC). – juanchopanza Jun 11 '14 at 05:32
  • I was hoping for a more official/documented explanation about this kind of use of parenthesis. I will look around. – Remy Lebeau Jun 11 '14 at 05:36
  • 10
    Both over 100k rep. This is an epic battle of the titans. – Fantastic Mr Fox Jun 11 '14 at 05:37
  • 2
    @RemyLebeau more info, http://stackoverflow.com/questions/24116817/when-do-extra-parentheses-have-an-effect-other-than-on-operator-precedence – M.M Jun 11 '14 at 05:57
  • 1
    similar case; `void f(int s);` is the same as `void f(int (s));`, this is the source of a lot of most-vexing-parse cases – M.M Jun 11 '14 at 06:05
  • @MattMcNabb: so `A(tmpVector);` == `A (tmpVector);` == `A tmpVector;`? – Remy Lebeau Jun 11 '14 at 06:05
  • The whitespace doesn't matter; if `A` is a typename then `A x;` and `A (x);` declares a variable `x` of type `A`. as does `A (((x)));` etc. – M.M Jun 11 '14 at 06:06
  • I think the relevant grammar line is *ptr-declarator: noptr-declarator* and *noptr-declarator: ( ptr-declarator )* – M.M Jun 11 '14 at 06:08
  • @RemyLebeau It may be down to the fact that constructors are nameless, so this cannot be a function call. And there is nothing that says that the parentheses have an effect in such a declaration/definition. – juanchopanza Jun 11 '14 at 06:08
  • Actually, I am not after passing default arguments. Just trying to define 3 different constructors, two of which are actually relying on the third one. From this point of view, this is similar to constructor delegation. Bur as far as I understand from [this link](https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/introduction_to_the_c_11_feature_delegating_constructors?lang=en), delegation is similar to passing default arguments. – fnisi Jun 11 '14 at 07:59
  • 3
    @MattMcNabb: I asked a [separate question](http://stackoverflow.com/questions/24155571) about the parenthesis issue and got a detailed answer with quotes from the standard that include the terms you mentioned. – Remy Lebeau Jun 11 '14 at 09:11
  • @FehmiNoyanISI: you may have wanted delegation, but that is not what you coded, because delegation only works in the constructor's initialization list, not the constructor body. Juanchopanza showed you how to do the delegation correctly. – Remy Lebeau Jun 11 '14 at 09:13
  • You might want to add that if one uses delegating constructors, the initialiser list is not allowed to contain any other member initialisers. [Source](http://en.cppreference.com/w/cpp/language/initializer_list) – iFreilicht Jun 11 '14 at 11:35
1

Thanks all, this is the final code, which was compiled smoothly by using mingw-w64 with GCC 4.8.1

A::A(const char *p) : A(string(p)) {
}

A::A(string s) : A(vector<string>{s}) {
}

A::A(vector<string> filePathVector) {
 // Do stuff here
}
fnisi
  • 1,181
  • 1
  • 14
  • 24