My code may be crashing because the 'class' isn't C compatible? - c++

-edit- I narrowed it down. Reproducible: Why does passing this object in C break my code?
My app is not working properly after i made a change. I got a warning in msvc but not in gcc.
Heres a repo of the warning.
warning C4190: 'fnA' has C-linkage specified, but returns UDT 'Test' which is incompatible with C
#include <type_traits>
template<class T>
class Test{
T t;
};
typedef Test<int> A;
//static_assert(std::is_pod<A>::value, "Not a POD"); //fails in msvc 2010
static_assert(sizeof(A) == sizeof(int), "");
static_assert(sizeof(A) == sizeof(void*), "");
extern "C" {
A fnA(A v) { return v; }
}
int main() {
A a;
fnA(a);
}
AFAIK there should be no reason why i can't use Test as a return value; This may not be the problem but this may be the problem. I can't figure out the problem but i get runtime oddities that i can not reproduce (both gcc and msvc). I suspected the problem would be MyString is corrupted but it appears that isnt the case which made me quite confused. Heres my wrapper. MyString is >8bytes and i need to hand this off to C code which returns everything by int unfortunately. Which is why i put the static assert to see if the class size is what i expected. Now that size/splicing is handled, i'm still completely like WTF!?! Why does that warning exist and is there anything i can possibly do to fix it?
Even writing class Test{ T t; }; causes the warning however struct fixes it. struct with private breaks it and i need t to be private.
OK! After I removed the constructors in WrappedPointer and changed the class to struct (which makes lhs public). It runs perfectly in GCC and MSVC. Changing struct WrappedPointer to class WrappedPointer breaks my code. WTF!?! This is a debug build too, not optimized. Why on earth does changing the keyword struct to class break the code!?! WTF!?! BUT that change doesnt break gcc. Using non default constructors break gcc...
template <class T>
struct WrappedPointer {
//private:
T* lhs;
public:
void SetLHS(T*v) { lhs=v; }
//WrappedPointer(){}
//WrappedPointer(T*value) : lhs(value){}
//WrappedPointer(const WrappedPointer&v) : lhs(v.lhs){}
T* operator->() const { return lhs; }
T* operator*() const { return lhs; }
template<class TT>
bool operator==(TT t) const { return *lhs==t; }
template<class TT>
bool operator!=(TT t) const { return *lhs!=t; }
bool operator==(int v) const { myassert2(v==0); return lhs==0; }
bool operator!=(int v) const { myassert2(v==0); return lhs!=0; }
bool operator==(const WrappedPointer&t) const { return *lhs==*t; }
bool operator!=(const WrappedPointer&t) const { return *lhs!=*t; }
}
typedef WrappedPointer<MyString> String;
//typedef MyString* String;
static_assert(sizeof(String) == sizeof(int), "");
static_assert(sizeof(String) == sizeof(void*),"");

The external "C" marks the function to have C linkage and disables name mangling. Now the issue in your function is that the argument is a template (the typedef only creates an alias in the current translation unit, A is still Test<int> for all purposes), and that name must be mangled.

extern "C" {
A fnA(A v) { return v; }
}
This says that fnA is a C function. C does not have object-oriented programming, or templates. The function uses both. Therefore, it cannot link as a C function.

Classes are not valid in C.
Templates are not valid in C.
Templated classes are certainly not valid in C.
Pick your language and stick to it!

Related

Alternative to returning template class in extern "C" with MSVC

I have the following class (and some specilization for certain types):
template <typename Type>
class SimpleOptional {
public:
SimpleOptional(Type content) : value_(true), content_(content) {}
// obviously simplified...
private:
bool value_;
Type content_;
};
which is part of a foreign function interface. The function must be declared with extern "C" like this:
extern "C" SimpleOptional<char*> b(char *a) {
return a + 4; // implicitly constructing SimpleOptional<char*>
}
This code works fine with GCC and Clang on macOS and Linux.
However MSVC does not like it and complains that a function with C linkage may not return a C++ class.
So far I came up with this (where MS_O will only be defined for MSVC):
template <typename Type>
class SimpleOptional {
public:
SimpleOptional(Type content) : value_(true), content_(content) {}
using ContentType = Type;
private:
bool value_;
Type content_;
};
#define MS_O(type) struct { bool b; type::ContentType v; }
extern "C" MS_O(SimpleOptional<char*>) b(char *a) {
return a + 4;
}
Although that fixes the return type issue, I still have no implicit construction and MSVC complains about not being able to convert char* to the return type.
Is there any kind of workaround that doesn't cost me C++ implicit construction?

locale Facet Constructor Ignored

The locale Facet constructor:
Constructs a copy of other except for the facet of type Facet (typically deduced from the type of the argument) which is installed from the argument facet. If facet is NULL, the constructed locale is a full copy of other. The locale constructed in this manner has no name.
I try to construct using my Facet here, but when I put a break-point in my do_decimal_point and do_thousands_sep they are never called :(
I can see the Facet being passed in, but it's passed into standard library implementation files so I can't see if anything is ever done with it.
I've tried this on Visual Studio 2013, Clang 3.6.0, and gcc 4.9.2. All of them behave as though I had never passed in a Facet just using the other locale's behavior.
I can't find any bugs against this constructor in any of the compilers. I think I'm doing this all the right way. Why can't I get locale to construct using my Facet?
EDIT:
At the request of 0x499602D2 I have added an example. It's interesting to note that the Facet does seem to be picked up but not used with get_money. I'm linking a live example of this (which necessarily useslocale("C") instead of locale("en-US")):
class Foo : public std::moneypunct<char> {
protected:
char_type do_decimal_point() const {
cout << "Hit Foo::do_decimal_point";
return ',';
}
char_type do_thousands_sep() const {
cout << "Hit Foo::do_thousands_sep";
return '.';
}
};
int main()
{
cout.imbue(locale(locale("en-US"), new Foo));
const moneypunct<char>* temp = &use_facet<std::moneypunct<char>>(cout.getloc());
cout << temp->decimal_point() << endl << temp->thousands_sep() << endl;
istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
USCurrency.imbue(cout.getloc());
long double value;
USCurrency >> get_money(value, true);
return 0;
}
This outputs:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
I would expect it to output:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
Hit Foo::do_thousands_sepHit Foo::do_decimal_point
EDIT2:
It appears that moneypunct<char> can't be inherited from as it doesn't get constructed properly, unless it is constructed internally by the locale. Which at least on Visual Studio is a problem because it determines whether to use thousands_sep by the grouping. The work around may be to completely reimplement moneypunct<char>'s functionality. I'm tinkering with that now. In the meantime I've also added a bug here: https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information
The fact is, do_decimal_place and do_thousands_place are respected by get_money. The difficulty is in the fact that the moneypunct that is being inherited from is being default constructed, so the supporting information to direct get_money to call do_decimal_place and do_thousands_place is not being set up.
Visual Studio's implementation of moneypunct provides two public constructors:
moneypunct()
moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)
locale's constructor calls the 2nd moneypunct constructor. Creating a proper _Locinfo is the crux of the problem as that information seems to be implementation specific. The linked Visual Studio Bug requests a way to construct a functional moneypunct without access to implementation details. In lieu of this information all moneypunct fields must be cooked up.
Since this question is about extending an expected working moneypunct the easiest way to do that would be to use an assignment operator or copy constructor. Bad news: both of those are deleted. So punct_facet(const money_punct&) will need to be written internally implementing the behavior of a copy constructor. The values that need to be copied correspond to all the virtual functions that need to be overridden and by punct_facet. In the end your class will end up looking similar to this:
template <typename T>
class punct_facet : public T {
protected:
typename T::string_type m_grouping;
typename T::string_type m_curr_symbol;
typename T::string_type m_positive_sign;
typename T::string_type m_negative_sign;
int m_frac_digits;
typename T::pattern m_pos_format;
typename T::pattern m_neg_format;
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
typename T::string_type do_grouping() const {
return m_grouping;
}
typename T::string_type do_curr_symbol() const {
return m_curr_symbol;
}
typename T::string_type do_positive_sign() const {
return m_positive_sign;
}
typename T::string_type do_negative_sign() const {
return m_negative_sign;
}
int do_frac_digits() const {
return m_frac_digits;
}
typename T::pattern do_pos_format() const {
return m_pos_format;
}
typename T::pattern do_neg_format() const {
return m_neg_format;
}
public:
punct_facet(const T& defaultFacet) : m_grouping(defaultFacet.grouping()),
m_curr_symbol(defaultFacet.curr_symbol()),
m_positive_sign(defaultFacet.positive_sign()),
m_negative_sign(defaultFacet.negative_sign()),
m_frac_digits(defaultFacet.frac_digits()),
m_pos_format(defaultFacet.pos_format()),
m_neg_format(defaultFacet.neg_format()) {}
};
EDIT:
This solution is cross platform but it is also unsatisfactory, because all the members that had to be added to punct_facet already exist in moneypunct. I am not aware of a clean workaround for this fattening. A compiler specific hack is available here: https://stackoverflow.com/a/31454039/2642059
This would result in a punct_facet that looked more like this given that Visual Studio places the v-table pointer as the first item in the object layout:
template <typename T>
class punct_facet : public T {
private:
void Init(const T* money){
const auto vTablePtrSize = sizeof(void*);
memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
}
protected:
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
public:
punct_facet(){
Init(&use_facet<T>(cout.getloc()));
}
punct_facet(const T* money){
Init(money);
}
};
Incidentally this implementation of punct_facet is not supported in Clang 3.6.0 but is supported in gcc 5.1.0: http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b

Why does this compile when I make the class a template?

I am purposely using the dot and arrow operator incorrectly, but I'm confused why it compiles when I decide to make the class a template.
Compiles:
template <class B>
struct Boss {
bool operator==( Boss & other ) {
return this.x == other -> x;
}
};
int main() {
}
Does not compile:
struct Boss {
bool operator==( Boss & other ) {
return this.x == other -> x;
}
};
int main() {
}
Templates are not fully checked for correctness if they are not instantiated. They are only checked for syntax. this.x, while not semantically correct (because this is not, and cannot be a type that supports that operation), is still syntactically correct.
It compiles because templates are not checked until you use it. If you try to do something useful in your main(), it will give you a compile error.

g++ strange warning

Working on a toy project that I started to answer an SO question I'm getting flooded by a g++ warning that I don't understand.
format.hpp:230: warning: dereferencing pointer ‘<anonymous>’
does break strict-aliasing rules
searching on the internet I've got the impression that this could be a g++ bug; is it really a bug and if yes is there any workaround for it? The full source code is too big for inclusion but is available here. Here is the part where the warning is triggered...
template<typename T>
class ValueWrapper : public ValueWrapperBase
{
public:
T x;
ValueWrapper(const T& x) : x(x) {}
virtual std::string toString(const Field& field) const
{
return Formatter<T>().toString(x, field);
}
private:
// Taboo
ValueWrapper(const ValueWrapper&);
ValueWrapper& operator=(const ValueWrapper&);
};
typedef std::map<std::string, ValueWrapperBase *> Env;
class Dict
{
private:
Env env;
public:
Dict() {}
virtual ~Dict()
{
for (Env::iterator i=env.begin(), e=env.end(); i!=e; ++i)
delete i->second;
}
template<typename T>
Dict& operator()(const std::string& name, const T& value)
{
Env::iterator p = env.find(name);
if (p == env.end())
{
env[name] = new ValueWrapper<T>(value);
}
else
{
ValueWrapperBase *vw = new ValueWrapper<T>(value);
delete p->second;
p->second = vw;
}
return *this;
}
const ValueWrapperBase& operator[](const std::string& name) const
{
Env::const_iterator p = env.find(name);
if (p == env.end())
throw std::runtime_error("Field not present");
return *(p->second);
}
private:
// Taboo
Dict(const Dict&);
Dict& operator=(const Dict&);
};
Line 230 is p->second = vw;.
I get the warning for every instantiation of the template method operator(), always about line 230.
EDIT
Apparently the bug is about the use of map iterators that can generate inline code that confuses the optimizer. Rewriting a section avoiding using iterators I got shorter code that also compiles cleanly without warnings.
template<typename T>
Dict& operator()(const std::string& name, const T& value)
{
ValueWrapperBase *vw = new ValueWrapper<T>(value);
ValueWrapperBase *& p(env[name]);
delete p;
p = vw;
return *this;
}
As far as I can tell this actually stems from code in map and not from your code itself.
According to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42032 and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43978 which both deal with maps and are very similar to each other, that there are absolutely some cases where it warns incorrectly because it loses track of the dynamic types of the objects. They equally state that there are some cases where it warms properly.
Also they indicate that the warning is shushed in 4.5 until they can implement it properly.
Finally, did you try rewriting your method as follows to see if it helps the warning in 4.3/4.4?
template<typename T>
Dict& operator()(const std::string& name, const T& value)
{
ValueWrapperBase *vw = new ValueWrapper<T>(value);
delete env[name];
env[name] = new ValueWrapper<T>(value);
return *this;
}
-fno-strict-aliasing (see http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Optimize-Options.html#index-fstrict_002daliasing-572) turns off gcc's strict aliasing optimisations, and (presumably) with it the warning.
See also What is the strict aliasing rule? and http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html.
I've seen this "error" before and decided that it's often meaningless. I don't see anything wrong with your code. You might try your luck with newer versions of GCC--I seem to recall seeing this pop up somewhere around 4.3-4.4.
Edit: I said this warning/error is "often" meaningless. Not "usually." I absolutely do not advocate simply ignoring or disabling warnings just because they are annoying, but in this code, and in some of my own code, there is no apparent problem despite GCC's complaint.

Problem with return type

I have a classes:
struct Policy_1
{
void signalFailure()
{
throw std::exception();
}
};
struct Policy_2
{
void* signalFailure()
{
return nullptr;
}
};
template<class Policy>
struct My
{
template<class T>
T* fnc(int value)
{
if (!value)
{
return Policy::signalFailure();//Here is the problem
}
else
{
return new int(value);
}
}
};
The problem is that depending on Policy class signalFailure either throws or returns nullptr but I'm getting error from compiler (even though Policy is set that it does throw) that it cannot convert void to (T*) - depending what I've substitute for tea; Now, I do understand where the problem lies - compiler does syntax check and discovers that from this Policy, signalFailure returns void so it can't parse it even though signalFailure in practice throws.
I have two options as I see it:
a) either declare void* as a result type of signalFailure
b) declare void as a result type in fnc and move the result type to a args list of this fnc
or
c) do some (and here is the real Q to you) macro or metaprogramming inside my fnc which would be determined at compile time (either return Policy::etc or just Policy::etc) and that I think would be the best option. Of course if someone of you has better and more elegant idea how to do it, is more than welcome to show it.
I see that you're using nullptr- which means that you must be in C++0x. In this case it is trivial to use decltype to solve this problem.
template<class Policy>
struct My
{
template<typename T> struct func_helper {
static T func() { return Policy::signalFailure(); }
};
template<> struct func_helper<void> {
static void* func() { Policy::signalFailure(); return nullptr; }
};
template<class T>
T* fnc(int value)
{
if (!value)
{
return func_helper<decltype(Policy::signalFailure())>::func();
}
else
{
return new int(value); // Compile error if int* cannot be converted
// to the type of the policy.
}
}
};
Edit: Hang on a second. This code is SERIOUSLY wrong. You're returning a new int(), as T*? This code doesn't need fixing, it needs the whole module ripping out.
I wouldn't be shocked if the throwing policy did have a return value, though unused, and that's probably what I would do. However, if you wan't to avoid void *, you could as well make the signalFailure methods template and call Policy::signalFailure<T>() from fnc (thus allowing the signalFailure methods to returned a more strongly typed T *).
On a side note, the signalFailure methods should either be static, or My should privately inherit from your Policy class.