I have this piece of code that compiles fine with clang (even with -Weverything), but for which gcc issues an error.
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
class PhonebookWriter
{
public:
PhonebookWriter(const string& fname):
fname_(fname), names_(), numbers_() {}
PhonebookWriter& operator()(const string& name,
const string& number)
{
names_.push_back(name);
numbers_.push_back(number);
return *this;
}
~PhonebookWriter(void)
{
ofstream f(fname_.c_str());
for(size_t i=0;i<names_.size();++i)
f << names_[i] << " " << numbers_[i] << "\n";
f.close();
}
private:
const string fname_;
vector<string> names_;
vector<string> numbers_;
};
namespace {
void write_guests_data(const string& fname)
{
PhonebookWriter(fname)("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
}
}
int main(void)
{
write_guests_data("phone_book.txt");
return 0;
}
and here's what I get when I try to compile the code:
$ g++ ./test.cpp
./test.cpp: In function ‘void {anonymous}::write_guests_data(const string&)’:
./test.cpp:39:27: error: declaration of ‘PhonebookWriter fname’ shadows a parameter
PhonebookWriter(fname)("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
^
./test.cpp:39:48: error: no matching function for call to ‘PhonebookWriter::PhonebookWriter(const char [11], const char [6])’
PhonebookWriter(fname)("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
^
./test.cpp:39:48: note: candidates are:
./test.cpp:11:3: note: PhonebookWriter::PhonebookWriter(const string&)
PhonebookWriter(const string& fname):
^
./test.cpp:11:3: note: candidate expects 1 argument, 2 provided
./test.cpp:7:7: note: PhonebookWriter::PhonebookWriter(const PhonebookWriter&)
class PhonebookWriter
^
./test.cpp:7:7: note: candidate expects 1 argument, 2 provided
./test.cpp:39:49: error: expected ‘,’ or ‘;’ before ‘(’ token
PhonebookWriter(fname)("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
^
My gcc version is 4.9.1, and my clang version is 3.5.0.
I don't understand why there should even be a shadowing problem. Even if there were, it should have been picked up by clang.
Change:
PhonebookWriter(fname)("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
to:
(PhonebookWriter(fname))("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
EXPLANATION
For some reason gcc removes the braces around fname, which turns the line into:
PhonebookWriter fname ("Mr Foo Bar","12345")("Mrs Bar Foo","54321");
And now the errors make sense.
Related
I have seen similar questions asked and tried their solutions but the answers to them do not seem to work. I have the following code:
.h
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::vector;
struct DialogueNode;
struct DialogueOption {
string text;
DialogueNode *next_node;
int return_code;
DialogueOption(string t, int rc, DialogueNode * nn) : text{t},
return_code{rc}, next_node{nn} {}
};
struct DialogueNode {
string text;
vector <DialogueOption> dialogue_options;
DialogueNode();
DialogueNode(const string &);
};
struct DialogueTree {
DialogueTree() {}
void init();
void destroyTree();
int performDialogue();
private:
vector <DialogueNode*> dialogue_nodes;
};
.cpp
#include "dialogue_tree.h"
DialogueNode::DialogueNode(const string &t) : text{t} {}
void DialogueTree::init() {
string s = "Hello";
for(int i = 0; i < 5; i++) {
DialogueNode *node = new DialogueNode(s);
dialogue_nodes.push_back(node);
delete node;
}
}
void DialogueTree::destroyTree() {
}
int DialogueTree::performDialogue() {
return 0;
}
int main() {
return 0;
}
I get the error: error: no matching function for call to ‘DialogueNode:: DialogueNode(std::__cxx11::string&)’ DialogueNode *node = new DialogueNode(s);
EDIT additional notes on error
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode()
dialogue_tree.h:17:8: note: candidate expects 0 arguments, 1 provided
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode(const DialogueNode&)
dialogue_tree.h:17:8: note: no known conversion for argument 1 from ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘const DialogueNode&’
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode(DialogueNode&&)
dialogue_tree.h:17:8: note: no known conversion for argument 1 from ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘DialogueNode&&’
Which makes no sense to me because I have the constructor defined to take a string as an argument.
You've declared your constructor as:
DialogueNode(const string);
But defined it as:
DialogueNode(const string &t);
Those two aren't the same; the former takes a const string while the latter takes a const string reference. You'll have to add the & to specify a reference argument:
DialogueNode(const string &);
it is because in the constructor you are specifying that the parameter will be a string of constant type and when creating an object you are passing a string. The type mismatch is the problem, either fix the constructor parameter to string or change when you are creating an object.
Consider the following C++ code:
#include <string>
struct A {
A(const std::string& s): s(s) {}
std::string s;
};
struct B: A {
using A::A;
};
int main() {
B b("test");
}
When I compile it via GCC 6.2.1 with the -Wuseless-cast parameter
g++ -std=c++14 -Wuseless-cast test.cpp -o test
it emits the following warning:
test.cpp: In constructor ‘B::B(const string&)’:
test.cpp:9:14: warning: useless cast to type ‘const string& {aka const std::__cxx11::basic_string<char>&}’ [-Wuseless-cast]
using A::A;
^
test.cpp: In function ‘int main()’:
test.cpp:13:15: note: synthesized method ‘B::B(const string&)’ first required here
B b("test");
^
However, when I change the definition of B to
struct B: A {
B(const std::string& s): A(s) {}
};
the warning goes away.
Questions:
Why is the warning emitted?
Why does specifying a constructor for B instead of inheriting it from A fixes the warning?
Your example can be further reduced to:
struct A {
A(const int& i): i(i) {}
int i;
};
struct B: A {
using A::A;
};
int main() {
B b(0);
}
That is an open issue on GCC.
Including <string> isn't apparently required to reproduce it.
Note that the issue is still unconfirmed and it is known to affect at least GCC 6.1 - by looking at your question I would say that it affects also GCC 6.2.
You are probably facing a known GCC bug (PR 70844).
In my actual code, I included a library, and as soon as I did that, it started crashing. I managed to sort of extract some of that code into this minimal example, that demonstrates the same kind of error:
// g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
#include <iostream>
#include <vector>
#include <stdio.h>
class Cat
{
public:
int Age;
Cat() : Age(0) {}
};
std::vector<Cat> myPCats;
typedef std::vector<Cat> TDVectCats;
TDVectCats myTDCats;
void loopSomeCats() {
printf("this function just to cause searching for matching calls\n");
}
void loopSomeCats(TDVectCats& incats) {
std::vector<Cat>::iterator iter;
for(iter = incats.begin(); iter != incats.end(); iter++) {
printf("hm\n");
}
}
const std::vector<Cat> & getSomeCats() {
return myPCats;
}
void doSomething() {
loopSomeCats(getSomeCats());
}
int main() {
myTDCats.push_back(Cat());
myTDCats.push_back(Cat());
myPCats.push_back(Cat());
doSomething();
std::cout << "Hello World! " << std::endl;
return 0;
}
The result is:
$ g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
test-classcall.cpp: In function ‘void doSomething()’:
test-classcall.cpp:36:29: error: no matching function for call to ‘loopSomeCats(const std::vector<Cat>&)’
loopSomeCats(getSomeCats());
^
test-classcall.cpp:36:29: note: candidates are:
test-classcall.cpp:20:6: note: void loopSomeCats()
void loopSomeCats() {
^
test-classcall.cpp:20:6: note: candidate expects 0 arguments, 1 provided
test-classcall.cpp:24:6: note: void loopSomeCats(TDVectCats&)
void loopSomeCats(TDVectCats& incats) {
^
test-classcall.cpp:24:6: note: no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’
What especially confuses me, is the last "no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’", as if it cannot convert a vector of something, into the vector of the same something, just because of typedef? Or it maybe has to do with the const - but I simply cannot see what I need to change, in order to have a call like loopSomeCats(getSomeCats()); succeed...
You can't pass a reference to a const object to a non-const reference.
loopSomeCats takes a std::vector<Cat>& as argument, and you want to pass a const std::vector<Cat>& to it, but that's not possible.
The const would mean that you don't want anyone to modify the return value, but if you pass it to a function which just takes a non-const reference, then theoretically the function can modify the reference, and you don't want that.
You should drop the const if you want the return value to be modified.
Here is a busybox I wrote to play with the new feature in gcc-4.8.1+ (I think clang-2.9+ should do this too) for N2439 (ref-qualifiers for 'this'):
class Foo
{
public:
Foo(int i) : _M_i(i) { }
int bar() & { return _M_i /= 2; }
int bar() const & { return _M_i; }
int bar() && { return 2 * _M_i; }
private:
int _M_i = 42;
};
int
main()
{
Foo ph(333);
ph.bar();
const Foo ff(123);
ff.bar();
Foo(333).bar();
}
It looks to me reading the standard 8.3.5 that the three bar() methods should be overloadable. I get a linker error though:
[ed#localhost ref_this]$ ../bin/bin/g++ -std=c++11 -o ref_this ref_this.cpp
/tmp/ccwPhzqr.s: Assembler messages:
/tmp/ccwPhzqr.s:73: Error: symbol `_ZN3Foo3barEv' is already defined
If I comment out int bar() const & I am unable to resolve ff.bar();:
[ed#localhost ref_this]$ ../bin/bin/g++ -std=c++11 -o ref_this ref_this.cpp
ref_this.cpp: In function ‘int main()’:
ref_this.cpp:26:10: error: no matching function for call to ‘Foo::bar() const’
ff.bar();
^
ref_this.cpp:26:10: note: candidates are:
ref_this.cpp:11:7: note: int Foo::bar() &
int bar() & { return _M_i /= 2; }
^
ref_this.cpp:11:7: note: no known conversion for implicit ‘this’ parameter from ‘const Foo’ to ‘Foo&’
ref_this.cpp:13:7: note: int Foo::bar() &&
int bar() && { return 2 * _M_i; }
^
ref_this.cpp:13:7: note: no known conversion for implicit ‘this’ parameter from ‘const Foo’ to ‘Foo&&’
Is this a gcc bug or part of the standard?
I'm not on my computer with clang on it but what does clang say?
This feature is not supported by GCC up to version 4.8.0. It should be supported by GCC 4.8.1, which has not been officially released yet.
To the best of my knowledge, the only major compiler that supports reference qualifiers on member functions at the moment is Clang. As you can see from this example, your code compiles fine on Clang 3.2.
I am trying to figure out how binders work. I am working on the example from HERE. So I decided to extend it a bit but I can't figure out what is wrong
namespace mine {
using std::bind1st;
using std::bind2nd;
using std::function;
};
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
int main()
{
using namespace mine;
// store a call to a member function
function<void(const Foo&, int)> f_add_display = &Foo::print_add;
Foo foo(314159);
f_add_display(foo, 1);
function<void(int)> foo_f_add_display = bind1st(f_add_display, foo);
foo_f_add_display(1);
// The problem is here <------------
function<void(const Foo&)> f_1_add_display = bind2nd(f_add_display, 1);
// f_1_add_display(foo);
}
The error message I am getting (from Intel CC, gdb is unintelligible)
Compilation finished with errors:
c++/4.7/backward/binders.h(160): error: invalid redeclaration of member function "std::binder2nd<_Operation>::operator()(const _Operation::first_argument_type &) const [with _Operation=std::function<void (const Foo &, int)>]" (declared at line 154)
operator()(typename _Operation::first_argument_type& __x) const
^
detected during instantiation of class "std::binder2nd<_Operation> [with _Operation=std::function<void (const Foo &, int)>]" at line 41 of "source.cpp"
compilation aborted for source.cpp (code 2)
What exactly is the problem here. Why is not possible to bind the second argument? or is it just some syntax error or something?
Code is HERE if anyone needs it.