C++ Class definition syntax - c++

when I tried to compile the following code I got an error:
"include/IBCppClient/client/SoftDollarTier.h|3|error: variable
‘TWSAPIDLLEXP SoftDollarTier’ has initializer but incomplete type|".
I guess the code is correct since it is part of a stock broker's API. But I struggle to understand the part on class definition "class TWSAPIDLLEXP SoftDollarTier". As far as I know, this syntax is not legal in C++. What did I miss?
class TWSAPIDLLEXP SoftDollarTier{
std::string m_name, m_val, m_displayName;
public:
SoftDollarTier(const std::string& name = "", const std::string& val = "", const std::string& displayName = "");
std::string name() const;
std::string val() const;
std::string displayName() const;
};

C++ allows macro definitions, which allow the C preprocessor to essentially find-and-replace these macros with more elaborate definitions. A common practice in C/C++ is to insert function attributes before their names using preprocessor macros, and what likely happened is that your environment does not include the header file which defines TWSAPIDLLEXP, so the compiler interprets the string as the class name.
From a quick search, it seems that TWSAPIDLLEXP is defined in tws-api (not sure if this is the same broker) as:
#define TWSAPIDLLEXP __declspec(dllimport)
in IBJts/samples/Cpp/TestCppClient/StdAfx.h.

Related

Is it possible to define a C++ member function who's definition is local to a file and therefore allow multiple versions to coexist

I'm trying to make a string class that can convert automatically to and from std::string.
class MyString
{
MyString(const std::string)
{
...
}
};
The issue is different compilers can have different layouts of std::string (e.g. Visual Studio 2010 vs 2015). So this constructor or autocast operator must be a function local to each compilation unit, AKA a static function. But you can't simply declare the member as static because the meaning isn't the same.
I know a guaranteed solution is to use a non-member function to do conversions and declare that as static. But would really appreciate a member function.
static MyString StringToMyString(const std::string& s);
I've considered forced inlining (even when optimizations are off), symbol aliasing, and symbol versioning and found forced inlining to be the simplest and most portable. __attribute__((alias)), requires the mangled C++ name and symbol versioning only works for shared libs and requires dynamic linker support. Here's an example that has 2 layouts for class My.
#include <stdio.h>
#define NO_INLINE __attribute__((noinline))
#define FORCE_INLINE __attribute__((always_inline))
class My
{
public:
FORCE_INLINE My(const String& s)
{
printf("creating from %s size=%d\n",s.s,(int)sizeof(s));
Construct(s.s);
}
NO_INLINE void Construct(const char* s)
{
printf("Construct(%s)\n",s);
}
};
void LibFunction();
#ifdef CLIENT
int main(int argc,char**argv)
{
String s;
s.s="string1";
My my(s);
LibFunction();
return 0;
}
#else
void LibFunction()
{
String s;
s.s="string2";
My my(s);
}
#endif
The output is this and is the same with or without optimizations
creating from string1 size=48
Construct(string1)
creating from string2 size=8
Construct(string2)
I've also investigated how QT deals with multiple layouts. In version 3.3, https://doc.qt.io/archives/3.3/qstring-h.html, it doesn't seem to:
class Q_EXPORT QString
{
QString( const std::string& );
};
Now, it's no longer a member function, but a private function to each compilation unit, presumably to allow multiple string layouts
class Q_CORE_EXPORT QString
{
static inline QString fromStdString(const std::string &s);
};

log4cxx - Locale looks like a function definition, but there is no parameter list

I am trying to compile a project that uses log4cxx, a c++ logging framework. Once I downloaded the framework and added it as a dependency, however, I get this error:
'Locale' : looks like a function definition, but there is no parameter list; skipping apparent body
This happens in locale.h which looks like this:
#ifndef _LOG4CXX_HELPERS_LOCALE_H
#define _LOG4CXX_HELPERS_LOCALE_H
#include <log4cxx/logstring.h>
namespace log4cxx
{
namespace helpers
{
class LOG4CXX_EXPORT Locale
{
public:
Locale(const LogString& language);
Locale(const LogString& language, const LogString& country);
Locale(const LogString& language, const LogString& country,
const LogString& variant);
const LogString& getLanguage() const;
const LogString& getCountry() const;
const LogString& getVariant() const;
protected:
Locale(const Locale&);
Locale& operator=(const Locale&);
const LogString language;
const LogString country;
const LogString variant;
}; // class Locale
} // namespace helpers
} // namespace log4cxx
#endif // _LOG4CXX_HELPERS_LOCALE_H
Is there anything wrong with this syntax? I am not knowledgeable in C++ at all but I do not see what would be wrong with it.
The one single thing on the internet I could find was this: https://issues.apache.org/jira/browse/LOGCXX-147 which makes perfect sense because I am targetting a windows ce device (although, using Visual Studio 2008 instead of 2005). The suggestion there is to include log4cxx/logstring.h inside "the cpp file" which I assume they mean locale.cpp although if I am clearly misinterpreting this please let me know. It said that would get rid of the compilation error but unfortunately I did that and it did not do anything to help :(.
I know it may be a bit of a longshot but does anyone know how one might fix this?

C++ declare exception in hpp file

I would like to modify PierreBdR's exception example of how to make a custom exception so that it is visible to other classes. His example works for me but the exception is visible only inside that class.
I'm using MS Visual Studio 2013 and I'm a C++ newbie encumbered by a Java mentality.
Here is what is in the .hpp file:
struct IllegalArgumentException : public std::exception
{
public: IllegalArgumentException(std::string ss);
public: ~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: std::string s;
};
Here is part of the .cpp file:
IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}
IllegalArgumentException::~IllegalArgumentException() {}
const char * IllegalArgumentException::what() { return s.c_str(); }
I'm getting:
error C2011: 'IllegalArgumentExcpetion': 'struct' type redefinition (.hpp file)
Point 1
const char* IllegalArgumentException::what() { return s.c_str(); }
is declared incorrectly if declared inside a class or struct. Since the declaration is being made inside the IllegalArgumentException class, IllegalArgumentException:: is implied and messes with the compiler because the compiler now thinks you are declaring something else. You want
const char* what() { return s.c_str(); }
In addition, the { return s.c_str(); } portion implements the function, so there is no need to implement it in the cpp file.
Point 2
Everything in a struct is public unless declared following the private keyword. This is the opposite of a class where everything is private unless stated otherwise. A class and a struct are pretty much identical other than the difference on default access.
Point 3
In C++ you can declare access level of members in blocks. There is no need to declare the access level of members one at a time.
struct IllegalArgumentException : public std::exception
{
// these are all public by default in a struct
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: // everything after this is private
std::string s;
int example;
};
or
class IllegalArgumentException : public std::exception
{
public: // these are all private by default in a class and need to be public
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: // switch back to private
std::string s;
int example;
};
or
class IllegalArgumentException : public std::exception
{
// these are all private by default in a class
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
};
Point 4
IllegalArgumentException::~IllegalArgumentException() {}
doesn't do anything. It doesn't need to do anything so the Rule of Zero recommends against having a destructor at all. The compiler will create it for you. If you don't have to write it, don't write it because code that doesn't exist has no bugs.
class IllegalArgumentException : public std::exception
{
// these are all private by default
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
const char* IllegalArgumentException::what() { return s.c_str(); }
};
Point 5
Stealing from KerrekSB here because it's a point that OP had another question on. Use Include Guards
Include guards prevent a header from being included multiple times in the same translation unit. This is a problem because of bloat and the possibility of the same thing being defined or declared more than once leading to confusion about which is the real one.
A simple header guard:
#ifndef ILLEGALARGUMENTEXCEPTION_H // if we've never seen ILLEGALARGUMENTEXCEPTION_H
// before, do the following
#define ILLEGALARGUMENTEXCEPTION_H // OK we've seen it now!
// all subsequent includes of IllegalArgumentException.h will have seen
// ILLEGALARGUMENTEXCEPTION_H and fail the ifndef, skipping everything
// until it finds the closing #endif
#include <string>
#include <exception>
class IllegalArgumentException : public std::exception
{
// these are all private by default
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
const char* IllegalArgumentException::what() { return s.c_str(); }
};
#endif // end of Include Guard
You may also use #pragma once, but be warned that #pragma means non-standard compiler extension. once may not exist for your compiler and if it doesn't, the compiler is allowed to skip the instruction without telling you!
There are many reasons why once is not in the standard, most important is it has unresolved fail cases. Use it with caution.
You mixed up the what() function's declaration and definition. You tried refer to the function with the scope resolution operator (i.e ::). In this case it should be done in the definition (i.e in the .cpp file)
Also the what() function was implemented as an inline function in your .hpp file, which means that you don't need to define it again in the .cpp file. Therefore you got a redefinition of ‘const char* IllegalArgumentException::what() error.
P.S: In C++ class declarations one does not need to specify every attribute/method's access modifier, you can just group them under a single modifier.
.hpp file:
struct IllegalArgumentException : public std::exception
{
public:
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* what() { return s.c_str(); }
private:
std::string s;
};
.cpp file:
IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}
IllegalArgumentException::~IllegalArgumentException() {}
It seems you are possibly, perhaps indirectly, including the .hpp file more than once?
#include is a fairly primitive way to share code among several .cpp files: it tells the compiler (the preprocessor, specifically) to import the contents of the .hpp right there at that spot in the code. Then in a later pass, the compiler will compile the entire thing as if it is all one file. (There's a whole crazy turing-complete language for that preprocessor step; IMO you should avoid it as much as possible, mostly only using it for the stuff outlined in this note.)
One problem with this approach is that if you end up importing one .hpp file more than once – a very common thing to do, since .hpp files typically include other .hpp files – you will have that code repeated. It's illegal to define a struct or class more than once, so you get the error about "type redefinition".
The solution is to use include guards in every single .hpp file. At the very top, use lines like:
#ifndef SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
#define SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
Then at the very bottom of the .hpp file:
#endif // SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
Those preprocessor directives, #ifndef, #define, etc will remove any text in the middle if the big unique string is already defined. Usually your codebase will establish conventions for that big string, such as encoding the path into it. My company even uses a lint tool to make sure you encoded it correctly.
This ensures that if you #include a .hpp twice, or #include another .hpp that includes an already-included .hpp, you will get the contents of the .hpp file exactly once in the final preprocessor output.
This, and the preprocessor in general, is one of the less charming parts of C++ that really shows its age. Soon the language will be getting a much more modern and pleasant system for sharing interfaces called "modules". In the meantime, each .hpp needs these 3 lines of boilerplate.
I am not sure, but I can comment so...
I think your "what" function is two times implemented:
First in your hpp file and then in the cpp file.

C linkage function cannot return C++ class - error resulting from the contents of my method

I am exporting a method that can be called from unmanaged code, but the function itself lives in a managed c++ project. The following code results in a compiler error:
error C2526: 'System::Collections::Generic::IEnumerator<T>::Current::get' : C linkage function cannot return C++ class 'System::Collections::Generic::KeyValuePair<TKey,TValue>'
error C2526: 'System::Collections::Generic::Dictionary<TKey,TValue>::KeyCollection::GetEnumerator' : C linkage function cannot return C++ class 'System::Collections::Generic::Dictionary<TKey,TValue>::KeyCollection::Enumerator'
extern "C"
__declspec( dllexport )
bool MyMethod(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
System::Collections::Generic::Dictionary<System::String ^, System::String^> _mgdMap = gcnew System::Collections::Generic::Dictionary<System::String ^, System::String ^>();
// Blah blah processing
}
Looking into this error a little bit, the issue normally has to do with the definition of the method that is marked as 'extern "C"'. So why would it be at all concerned with what goes on inside the method?
If I comment out the Dictionary initialization, or switch it to a HashTable everything compiles beautifully.
The following works as well - if instead of defining a dictionary locally, I avoid the local variable by initializing it in a method.
bool status = CallAnotherMethod(ConvertToDictionary(mymap));
where ConvertToDictionary is declared as
System::Collections::Generic::Dictionary<System::String ^, System::String ^>^ ConvertToDictionary(std::map<std::string, std::string> &map)
{
}
Which tells me that this is a seemingly arbitrary error. I would still like to understand why the compiler thinks this is a problem.
Sorry for necroposting but i need to share my happiness with somebody :)
Seems that you are able to solve this just by creating two wrappers - one for external call marked with "extern C" and one for internal call. In this case everything outside "extern C" will be executed as usual .NET code.
That was answered by the topicstarter here - C++/CLI->C# error C2526: C linkage function cannot return C++ class
void DummyInternalCall(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
System::Collections::Generic::Dictionary<System::String ^, System::String^> _mgdMap = gcnew System::Collections::Generic::Dictionary<System::String ^, System::String ^>();
// Blah blah processing
}
extern "C" __declspec( dllexport )
bool MyMethod(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
DummyInternalCall(name, path, mymap);
}
If you write a function in C++ that is to be called from C, you can't use anything in it's interface (arguments and return type) that isn't plain C. Here all your arguments are C++ objects.

Unqualified-id before string constant

On compiling following code I get error "expected unqualified-id before string constant"
In file "Notification_Constants.h"
namespace NOTIFICATION_CONSTANTS
{
#define SERVICE_EMAIL "service#company.com"
}
In file SendEmail.cpp
#include "Notification_Constants.h"
void UserPreferences::get_senders_email(String &_email)
{
_email = NOTIFICATION_CONSTANTS::SERVICE_EMAIL;
}
If i assign like following it works properly, what is the reason for the compilation error.
_email = SERVICE_EMAIL;
There is a similar question but the reason is not mentioned.
String class declaration with relevant methods
class String
{
public:
String();
String(const String& src);
String(const char *new_str);
String& operator=(const String& src);
String& operator=(const char *new_str);
};
First, you should put quotation marks around the email address:
#define SERVICE_EMAIL "service#company.com"
Second, you should not use #define at all. Use a const variable instead:
const String SERVICE_EMAIL = "service#company.com";
#defines are type unsafe, have no scope and are generally evil.
Last, you may want to consider using std::string instead of your String class.
Update:
The problem is that the preprocessor #defines are nothing more than text substitutions. When the preprocessor is done, your compiler will see
_email = NOTIFICATION_CONSTANTS::"service#company.com";
There is no string constant in that namespace. SERVICE_EMAIL is not an identifier of any kind - it is just an indication to the preprocessor to substitute any occurrence of SERVICE_EMAIL with "service#company.com".
The solution is to remove the namespace qualifier:
_email = SERVICE_EMAIL;
Better solution:
If you do not have access to the #define, you should wrap it in a header file, if possible:
#include "Notification_Constants.h"
namespace NOTIFICATION_CONSTANTS {
const String REAL_SERVICE_EMAIL = SERVICE_EMAIL;
}
and then use NOTIFICATION_CONSTANTS::REAL_SERVICE_EMAIL instead, which has scope, is a type, is a proper member of the namespace, and so on.
The problem is, I think since I don't know the String type, is that SERVICE_EMAIL should be a string literal:
#define SERVICE_EMAIL "service#company.com"
but then, it should fail even in the latter solution. Maybe your code snippet doesn't show the real problem.
#define SERVICE_EMAIL "service#company.com"
What's the type of service#company.com?
I think you wish to use a string to store an email address.
Try:
#define SERVICE_EMAIL "service#company.com"