In the code below, the line
const char * const * eNames (names+cntNames);
results in a C2061 error in Visual Studio 2008:
syntax error : identifier 'identifier' -
The compiler found an identifier where it wasn't expected.
Make sure that identifier is declared before you use it.
An initializer may be enclosed by parentheses.
To avoid this problem, enclose the declarator in parentheses or make it a typedef.
This error could also be caused when the compiler detects an expression as a class
template argument; use typename to tell the compiler it is a type.
If I change to
const char * const * eNames = names+cntNames;
it doesn't complain. Is this a compiler bug? If not, why the complaint?
My About box says: Version 9.0.30729.1 SP
My colleague with GCC does not see this error.
#include <string>
#include <algorithm>
#include <functional>
#include <iostream>
namespace ns1 {
struct str_eq_to
{
str_eq_to(const std::string& s) : s_(s) {}
bool operator()(const char* x) const { return s_.compare(x)==0; }
const std::string& s_;
};
static bool getNameIndex(const char * const * names, size_t cntNames, const std::string& nm, int &result)
{
const char * const * eNames (names+cntNames); //VS2008 error C2061: syntax error : identifier 'names'
const char * const * p = std::find_if(names, eNames, str_eq_to(nm));
if(p==eNames) return false;
result = p-names;
return true;
}
} //namespace ns1
int main() {
const char * const names[] = {"Apple", "Orange","Plum"};
std::string str = "Plum";
int res;
ns1::getNameIndex(names, 3, str, res);
std::cout << str << " is at index " << res << std::endl;
return 0;
}
This is most definitely a compiler bug. Witness:
extern char** a;
typedef char* cp;
char** c(a); // error
cp* c1(a); // no error
char** c2(c1); // error
cp* n(0); // no error
char** n2(0); // error
Related
The following code compiles with clang v5.0.0 and g++ v8.1.0 but fails with visual studio (2013 and 2017):
#include <string>
#include <functional>
#include <iostream>
template <const char* name>
std::string fct() {
return name;
}
const char toto[] = "toto";
std::function<std::string()> fctptr = fct<toto>;
int main(){
std::cout << fctptr() << std::endl;
}
The error is the following:
main.cpp(11): error C2440: 'initializing' : cannot convert from 'std::string (__cdecl *)(void)' to 'std::function<std::string (void)>'
1> No constructor could take the source type, or constructor overload resolution was ambiguous
I tried to replace the std::function with a typedef to a function pointer, as such:
typedef std::string(*Fctptr)();
Fctptr fctptr = fct<toto>;
However, I got the same error.
Is it a bug with msvc compiler, or is the above code not standard compliant.
FWIW, the following failed to compile using g++ 6.4.0 (g++ -std=c++11).
#include <string>
#include <functional>
#include <iostream>
template <const char* name>
std::string fct() {
return name;
}
const char toto[] = "toto";
std::function<std::string()> fctptr = fct<toto>;
int main(){
std::cout << fctptr() << std::endl;
}
Here's the error message:
socc.cc:11:43: error: the value of ‘toto’ is not usable in a constant expression
std::function<std::string()> fctptr = fct<toto>;
^~~~
socc.cc:10:12: note: ‘toto’ was not declared ‘constexpr’
const char toto[] = "toto";
Changing the definition of toto to
constexpr char toto[] = "toto";
resolved the problem.
I know this question has been asked before, but it's a clear issue in every other case. Everyone accidentally called their constructor twice. I, on the other hand, am having this issue because of prototypes in a header file, and it makes no damn sense. I'm having the error called on every single function called between these two files. Thanks!
Auto.h
#ifndef AUTO_H
#define AUTO_H
#include<string>
using std::string;
class Auto
{
public:
Auto();
Auto(const char* mk, const char* ml, int d);
void setDoors(int d);
int getDoors(void) const;
const string getMake(void) const;
const string getModel(void) const;
void setMake(const char *mk);
void setModel(const char *ml);
private:
int doors;
string make;
string model;
};
#endif
Auto.cpp
#include "Auto.h"
Auto::Auto()
{
// The strings are constructed empty by their default construtors
doors = 2;
}
Auto::Auto(const char* mk, const char* ml, int d)
{
setMake(mk);
setModel(ml);
setDoors(d);
return;
}
void Auto::setDoors(int d)
{
if (d>0)
doors = d;
else
doors = 2;
return;
}
int Auto::getDoors(void) const
{
return doors;
}
const string Auto::getMake(void) const
{
return make;
}
const string Auto::getModel(void) const
{
return model;
}
void Auto::setMake(const char *mk)
{
if (mk != 0) {
make = mk;
}
return;
}
void Auto::setModel(const char *ml)
{
if (ml != 0) {
model = ml;
}
return;
}
Error messages:
1> Lab11.cpp 1>m:\cosc1030\lab11\lab11\lab11\auto.cpp(14): error C2084: function 'Auto::Auto(void)' already has a body
1> m:\cosc1030\lab11\lab11\lab11\auto.h(18) : see previous definition of '{ctor}' 1>m:\cosc1030\lab11\lab11\lab11\auto.cpp(20): error C2084: function 'Auto::Auto(const char *,const char *,int)' already has a body
1> m:\cosc1030\lab11\lab11\lab11\auto.h(19) : see previous definition of '{ctor}'
I have a problem to pass my own class as a parameter.
Here is my codes:
PayloadContainer.h
namespace Project
{
namespace C
{
namespace Helper
{
class PayloadItem
{
public:
string Key;
string Value;
char Type;
char Mode;
char IsArray;
int FieldCount;
char FieldType;
int RowCount;
};
class PayloadContainer
{
public:
PayloadContainer( const char *Command );
PayloadContainer(void);
~PayloadContainer(void);
public:
vector<PayloadItem> PayloadItems;
};
}
}
}
ParseBinary.h
namespace Project
{
namespace C
{
namespace Helper
{
class ParseBinary
{
public:
ParseBinary(void);
~ParseBinary(void);
private:
void WriteRequestToBinary( const char *BinFileName );
void WriteRequestRecord( unsigned char file[], PayloadItem& item, string charSet );
};
}
}
}
ParseBinary.cpp
namespace Project
{
namespace C
{
namespace Helper
{
void ParseBinary::WriteRequestToBinary( const char *BinFileName )
{
unsigned char in;
// Do Something
for (auto &item : _payload->PayloadItems)
{
// Do Something
WriteRequestRecord( in, (Helper::PayloadItem)item, _payload->CharSet );
}
}
void ParseBinary::WriteRequestRecord( unsigned char file[], PayloadItem& item, string charSet )
{
-----> here, I get "error C2511: overloaded member function not found".
}
}
}
}
What I am trying to do is iterating vector where PayloadItem is my own class, and pass that class to a function.
But, when I build it I get this error C2511: overloaded member function not found error.
Please tell me where to fix this.
EDIT
This is the error message.
Error 9 error C2061: syntax error : identifier 'PayloadItem' c:\webdev\Project.c.helper\ParseBinary.h 46 1 Project.C.Helper
error C2511: overloaded member function not found in 'Project::C::Helper::ParseBinary' c:\webdev\Project.c.helper\ParseBinary.cpp 958 1 Project.C.Helper
My below code is giving me compiler error and I an not understanding what wrong I am doing. Can anyone help please?
Basically all I am trying to do is pass a STL map container by reference to a function which would fill it up. This map container also has a comparator lambda associated with it.
#include "stdafx.h"
#include <functional>
#include <map>
using namespace std;
typedef struct _tagAddressBook
{
string strFirstName;
string strLastName;
long nZipCode;
} AddressBook;
void foo(map<string, AddressBook, function<bool(const string&, const string&)>> &myAddressBook)
{
AddressBook addressBookInstance;
addressBookInstance.strFirstName = "Bob";
addressBookInstance.strLastName = "Parker";
addressBookInstance.nZipCode = 12345;
myAddressBook.insert(std::pair<string, AddressBook>(addressBookInstance.strFirstName, addressBookInstance));
}
int _tmain(int argc, _TCHAR* argv[])
{
auto myComparator = [] (const string &strLeft, const string &strRight) { return(strLeft.compare(strRight) <= 0 ? true : false); };
map<string, AddressBook, decltype(myComparator)> myAddressBook(myComparator);
foo(myAddressBook);
return 0;
}
I get the below compilation error on VS2012
Error 1 error C2664: 'foo' : cannot convert parameter 1 from 'std::map<_Kty,_Ty,_Pr>' to 'std::map<_Kty,_Ty,_Pr> &' d:\my projects\mapwithlambdacomparator\mapwithlambdacomparator\mapwithlambdacomparator.cpp 32
2 IntelliSense: a reference of type "std::map<std::string, AddressBook, std::function<bool (const std::string &, const std::string &)>, std::allocator<std::pair<const std::string, AddressBook>>> &" (not const-qualified) cannot be initialized with a value of type "std::map<std::string, AddressBook, lambda []bool (const std::string &strLeft, const std::string &strRight)->bool, std::allocator<std::pair<const std::string, AddressBook>>>" d:\My Projects\MapWithLambdaComparator\MapWithLambdaComparator\MapWithLambdaComparator.cpp 32
Lambda functions are not related to std::function. In fact, each is its own class type. If you want to do what it appears you do, you can do it by template through foo and let deduction sort it out.
template <typename Cmp>
void foo(map<std::string, AddressBook, Cmp> &myAddressBook)
{
AddressBook addressBookInstance;
addressBookInstance.strFirstName = "Bob";
addressBookInstance.strLastName = "Parker";
addressBookInstance.nZipCode = 12345;
myAddressBook.insert(std::pair<string, AddressBook>(addressBookInstance.strFirstName, addressBookInstance));
}
This works on my toolchain, "Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)". I see no reason it would not work with your toolchain as well.
Please make an alias:
using AdressBookMap = map<string, AddressBook, function<bool(const string&, const string&)>>;
Then use it:
void foo(AddressBookMap& myAddressBook)
{
// ...
}
int main(int argc, char* argv[])
{
auto myComparator = [] (...) { ... };
AddressBookMap myAddressBook(myComparator);
foo(myAddressBook);
return 0;
}
As Whoz said, lambdas are not std::function; the latter can be implicitly constructed from the former, but they don't have the same type. This means a std::map parametrized by one is completely unrelated to a std::map parametrized by the other.
The following code compiles in Visual Studio 2010 but fails to compile in the Visual Studio 2012 RC.
#include <string>
// Windows stuffs
typedef __nullterminated const wchar_t *LPCWSTR;
class CTestObj {
public:
CTestObj() {m_tmp = L"default";};
operator LPCWSTR() { return m_tmp.c_str(); } // returns const wchar_t*
operator std::wstring() const { return m_tmp; } // returns std::wstring
protected:
std::wstring m_tmp;
};
int _tmain(int argc, _TCHAR* argv[])
{
CTestObj x;
std::wstring strval = (std::wstring) x;
return 0;
}
The error returned is:
error C2440: 'type cast' : cannot convert from 'CTestObj' to 'std::wstring'
No constructor could take the source type, or constructor overload resolution was ambiguous
I've already realized that commenting out either of the conversion operators fixes the compile problem. I just want to understand:
What's going on under the hood to cause this
Why this compiles in VS2010 and not in VS2012? Is it because of a C++11 change?
If I'm understanding the logic under the hood, the operator overload is trying to copy the code and the object every time you cast. Therefore, you need to return it as a reference instead of attempting to return a new object based on the field. The line:
operator std::wstring() const { return m_tmp; }
should be:
operator std::wstring&() { return m_tmp; }
The following compiles and runs as expected.
#include <string>
// Windows stuffs
typedef __nullterminated const wchar_t *LPCWSTR;
class CTestObj {
public:
CTestObj() {m_tmp = L"default";};
operator LPCWSTR() { return m_tmp.c_str(); } // returns const wchar_t*
operator std::wstring&() { return m_tmp; } // returns std::wstring
protected:
std::wstring m_tmp;
};
int main()
{
CTestObj x;
std::wstring strval = (std::wstring) x;
wprintf(L"%s\n", strval.c_str());
return 0;
}