I have simple code.
template<typename T>
class NamedObject{
public:
NamedObject(std::string& name, const T& value):nameValue(name), objectValue(value)
{
}
private:
std::string& nameValue;
const T objectValue;
};
int main(int argc, char* argv[])
{
NamedObject<int> no1("Smallest Prime Number",2);//error
NamedObject<int> no2(std::string("Smalledst Prime Number"),2);//works
return 0;
}
When I make first parameter as non refrence, both no1 and no2 object gets created. But when I keep reference Visual Studio compiler gives following error,
Error 1 error C2664: 'NamedObject::NamedObject(std::string &,const
T &)' : cannot convert parameter 1 from 'const char [22]' to
'std::string &' c:\users\pkothari\documents\visual studio
2008\projects\stackoflw\stackoflw\stackoflw.cpp 36
If char * can be casted to std::string, why not to std::string& ? Is there any way to make it work?
NamedObject<int> no2(std::string("Smalledst Prime Number"),2);//works
That should not work in a standard compliant compiler. It is supported in MS Visual Studio C++ even though it is not standard C++.
Neither of the following calls should work when the expected argument is std::string&.
NamedObject<int> no1("Smallest Prime Number",2);
NamedObject<int> no2(std::string("Smalledst Prime Number"),2);
Both of them should work when the argument type is std::string or std::string const&.
Related
Here is the code:
vector<ClientInfo*> OpenRABiz::GetHumans() const {
vector<ClientInfo*> vec;
for (auto &c : clients) {
if (!c.isbot) {
vec.push_back(&c);
}
}
return vec; // RVO - return value optimization
}
In visual c++ 2019, compiler indate it:
error C2664: 'void std::vector<ClientInfo *,std::allocator<ClientInfo *>>::push_back(_Ty &&)': cannot convert argument 1 from 'const ClientInfo *' to 'const _Ty &'
The error message: "
const _Ty&" means the c++ template can't deduce the right parameters
.
When I take the const keyword, it compiles successfully.
vector<ClientInfo*> OpenRABiz::GetHumans()
Why?
Your clients is likely a vector of ClientInfo, so in a const-qualified member-functions, the type of client (in the loop) is const ClientInfo&. When you take the address &client, you get a const ClientInfo*, which cannot be converted to a ClientInfo*.
When you remove the const-qualifier, everything works fine because client is then ClientInfo&.
To fix the issue, change the return-type of the function and declaration of vec to std::vector<const ClientInfo*>.
My issue is best demonstrated by the following code:
#include <fstream>
#include <iterator>
class Bar
{
public: template <class Iterator> Bar(Iterator first, Iterator last) {}
};
void foo(const Bar& bar) { }
int main(int argc, char** argv)
{
std::ifstream file("file.txt");
Bar bar(std::istream_iterator<char>(file), std::istream_iterator<char>());
foo(bar); // error C2664: 'foo' : cannot convert parameter 1 from 'Bar (__cdecl *)(std::istream_iterator<_Ty>,std::istream_iterator<_Ty> (__cdecl *)(void))' to 'const Bar &'
// with
// [
// _Ty=char
// ]
// Reason: cannot convert from 'overloaded-function' to 'const Bar'
// No constructor could take the source type, or constructor overload resolution was ambiguous
return 0;
};
Here are some similar instantiations of bar that don't cause the same ambiguity:
Bar bar = Bar(std::istream_iterator<char>(file), std::istream_iterator<char>());
and
std::istream_iterator<char> start(file);
std::istream_iterator<char> end;
Bar bar(start, end);
My question is, what is it about the first declaration of bar that causes it to be misinterpreted?
note: I'm testing with Visual Studio 2010 (10.0.30319.1)
ArunMu gets partial credit, it is indeed an example of Most Vexing Parse, but that term was coined in Meyer's Effective STL (Chapter 1, Item 6) not Exceptional C++.
It is being interpreted as a function pointer (the (__cdecl *) portion of the error is a dead give away), and apparently the C++ standard requires it to be interpreted that way. Does anyone have a chapter/verse citation for that?
There is also a another solution to provide a disambiguation. Adding an additional set of parenthesis around each parameter works too:
Bar bar( (std::istream_iterator<char>(file)), (std::istream_iterator<char>()) );
It's also worth pointing out that the issue is unrelated to the templates, as I had originally thought.
I think it is related to "C++ most vexing parse" that you will find in Meyer's Effective STL book.
Bar bar(std::istream_iterator< char >(file), std::istream_iterator < char >());
Is being considered as a **function declaration.**
due to which in foo(bar); you are sending a function pointer instead :)
Doing like below will have no error:
Bar bar = Bar(//your arguments here);
foo(bar);
My question is about a specific item (3) of the book "Effective C++". The book gives this example that I tried to reproduce as close as possible into vs 2010 c++ (including iostream and string):
class TextBlock {
public:
const char& operator[](std::size_t pos) const
{
return text[pos];
}
char& operator[](std::size_t pos)
{
return text[pos];
}
private:
std::string text;
};
void print(const TextBlock& ctb)
{
std::cout << ctb[0]; // OK
//ctb[0] = ‘A’; // Not OK – compiler error
}
int _tmain(int argc, _TCHAR* argv[])
{
TextBlock tb(“Hello”);
std::cout << tb[0];
tb[0] = ‘x’; // OK because return has &, not const
const TextBlock ctb("World");
std::cout << ctb[0];
return 0;
}
And I get these compiling errors:
1>c:\users\lalancelot\documents\visual studio 2010\projects\item3\item3.cpp(31): error C2065: '“Hello”' : undeclared identifier
1>c:\users\lalancelot\documents\visual studio 2010\projects\item3\item3.cpp(33): error C2065: '‘x’' : undeclared identifier
1>c:\users\lalancelot\documents\visual studio 2010\projects\item3\item3.cpp(34): error C2664: 'TextBlock::TextBlock(const TextBlock &)' : cannot convert parameter 1 from 'const char [6]' to 'const TextBlock &'
1> Reason: cannot convert from 'const char [6]' to 'const TextBlock'
1> No constructor could take the source type, or constructor overload resolution was ambiguous
Let me first say that I am discouraged to already be stuck at this early stage of the book. I have somehow found informations here:
difference between static_cast<const A>(*this) and static_cast<const A&>(*this),
but not a working answer like the one in the book. I would like to make the book example work so I can understand how it works. I've been stuck on this one for many days now and I must admit that I need help. I would like to know if I am missing a base concept here or if I am way over my head. Thanks.
What kind of quotes are you using? I ask because when I look at your
code, I see distinct opening and closing quotes, and when I copy/paste
it into my editor, it indicates that they are Unicode opening and
closing quotes. All punctuation in a C++ program should be pure
ASCII: 0x22 for the double quotes (both opening and closing), and 0x27
for the single quotes. This is also what the corresponding characters
on the keyboard should give you when entering text in a program
editor. (Do not use a word processor for entering code.)
The class TextBlock needs a constructor to be constructable from a text:
explicit TextBlock( const std::string& s ) : text( s )
{
}
Maybe there is a website to the book where you can look up corrections to the book.
I have made a test case to show the problems I am running into. Please forgive me my ignorance on the issues of Deferred libraries and pointer casting. The only library included in the deferred.lib.
#include <deferred/deferred.h>
using namespace deferred;
SafePtr<Deferred> recordTime(int time)
{
SafePtr<Deferred> d = createDeferred();
SafePtr<CallbackData> p = new PointerCBD< char>( 0 );
d->execute(p);
return d;
}
int main(int argc, char* argv[])
{
while(1)
{
SafePtr<Deferred> d = recordTime(1000);
d->waitHereForCompletion();
char* c = dynamic_pointer_cast<char>(d->endResult());
}
return 0;
}
When I try and compile in Windows XP with VS2008 I get:
Error C2440: 'initializing' : cannot convert from
'deferred:SafePtr' to 'char *' with
[T=char]
No user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called.
I have tried this command to return a pointer, rather than a SafePtr:
ManagerTimings* t = dynamic_pointer_cast<ManagerTimings>(d->endResult()).get();
Then I get this error:
Error C2664: 'deferred::intrusive_ptr_release' : cannot convert
parameter 1 from 'char *' to
'deferred:ReferenceCountable *'
I have tried this command:
ManagerTimings* t = dynamic_pointer_cast<ManagerTimings>(d->endResult().get());
Then I get this error:
Error C2784: 'deferred::SafePtr deferred::dynamic_pointer_cast(const deferred::SafePtr< U > &)' : could not deduce template argument for 'const deferred::SafePtr< U > &' from 'deferred::CallbackData *'
Try this:
ManagerTimings* t = dynamic_pointer_cast<ManagerTimings>(d->endResult().get());
if you want to get an "unsafe" pointer, or probably this:
SafePtr<ManagerTimings> t= dynamic_pointer_cast<ManagerTimings>(d->endResult());
to get a safe ManagerTimings pointer. I don't know what library you are using, but I suspect that dynamic_pointer_cast can convert a SafePtr to another SafePtr. Or it just converts pointers.
&*d->endResult()
I think from this code endResult is the SafePtr you're having trouble with.
I am having a problem with command line parsing with boost:program_options. The quickest way to explain it is to show the code so:
const std::vector<tstring> args;
if (ac > 0 && NULL!=av) //ac is a ULONG
{
for (int i = 0; i < ac; i++)
{
args.push_back(av[i]); //av is an LPTSTR pointer (pointer to TCHAR*)
}
}
po::command_line_parser parser(args);
The parser ctor is supposed to take a const std::vector<charT>
typedef basic_command_line_parser<char> command_line_parser;
typedef basic_command_line_parser<wchar_t> wcommand_line_parser;
/** Creates instance of 'command_line_parser', passes parameters to it,
and returns the result of calling the 'run' method.
*/
template<class charT>
class basic_command_line_parser : private detail::cmdline {
public:
/** Creates a command line parser for the specified arguments
list. The 'args' parameter should not include program name.
*/
basic_command_line_parser(const std::vector<
std::basic_string<charT> >& args);
tstring in my program is
typedef std::basic_string<TCHAR> tstring;
The error I get is:
Error 16 error C2664: 'boost::program_options::basic_command_line_parser<charT>::basic_command_line_parser(const std::vector<_Ty> &)' : cannot convert parameter 1 from 'const std::vector<_Ty>' to 'const std::vector<_Ty> &' myfile.cpp 329
Where, oh where, am I going astray? I've tried all kinds of casting and re-defining, but nothing has worked and I'm at the end of my tether.
Edit #Zac:
Making the changes you suggested... I get the error:
Error 14 error C2664: boost::program_options::basic_command_line_parser<charT>::basic_command_line_parser(const std::vector<_Ty> &)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'const std::vector<_Ty> &' MyFile.cpp 328
Edit
Just to point out that I am using Visual Studio 2008 VC9 compiler
You seem to be using a unicode build, so either explicitly use the wide char version:
po::wcommand_line_parser parser(args);
or the more flexible:
po::basic_command_line_parser<TCHAR> parser(args);
The line you went astray with is below:
const std::vector<tstring> args;
Change it to:
std::vector<tstring> args;