#include <wx/longlong.h>
#include <wx/string.h>
int main() {
wxLongLong id;
wxString::Format( "%lld", id );
}
There's lot of code like this in the application, and it
apparently compiles fine with Microsoft Visual C++ (not sure
which version as I don't have a copy of Windows to try it),
but it won't compile with either gcc 4.4.3 or gcc 4.6.0
using either wxWidgets 2.9.1 or 2.8.10. See below for the
output of the compilation.
------ Compile log ------
richard@nevis:~$ g++ foo.cpp `wx-config-2.9 --cxxflags --libs`
In file included from /home/richard/include/wx-2.9/wx/longlong.h:20,
from foo.cpp:1:
/home/richard/include/wx-2.9/wx/string.h: In static member
function ‘static wxString wxString::Format(const
wxFormatString&, T1) [with T1 = wxLongLongNative]’:
foo.cpp:6: instantiated from here
/home/richard/include/wx-2.9/wx/string.h:2325: warning:
cannot pass objects of non-POD type ‘class wxLongLongNative’
through ‘...’; call will abort at runtime
foo.cpp:6: instantiated from here
/home/richard/include/wx-2.9/wx/string.h:2325: warning:
cannot pass objects of non-POD type ‘class wxLongLongNative’
through ‘...’; call will abort at runtime
In file included from /home/richard/include/wx-2.9/wx/string.h:53,
from /home/richard/include/wx-2.9/wx/longlong.h:20,
from foo.cpp:1:
/home/richard/include/wx-2.9/wx/strvararg.h: At global scope:
/home/richard/include/wx-2.9/wx/strvararg.h: In instantiation of
‘wxFormatStringSpecifier<wxLongLongNative>’:
/home/richard/include/wx-2.9/wx/strvararg.h:449:
instantiated from ‘wxArgNormalizer<T>::wxArgNormalizer(T,
const wxFormatString*, unsigned int) [with T = wxLongLongNative]’
/home/richard/include/wx-2.9/wx/strvararg.h:481: instantiated from
‘wxArgNormalizerUtf8<T>::wxArgNormalizerUtf8(T, const
wxFormatString*, unsigned int) [with T = wxLongLongNative]’
/home/richard/include/wx-2.9/wx/string.h:2325:
instantiated from ‘static wxString wxString::Format(const
wxFormatString&, T1) [with T1 = wxLongLongNative]’
foo.cpp:6: instantiated from here
/home/richard/include/wx-2.9/wx/strvararg.h:347: error:
‘value’ is not a member of
‘wxFormatStringSpecifierNonPodType<false>’
------ End compile log ------
I can fix it by changing id to id.GetValue(), but this would
be a very intrusive change to the code base -- the construct
appeals getting on for a thousand times -- and there's no
guarantee the patch would be accepted upstream. It's clear
that wxString::Format can handle some non-POD-types, so I'm
hoping it can handle wxLongLong too, especially as it seems
to work with Visual C++.
Is there some trick to compiling this? Perhaps a -D on the
command-line that I'm missing, or a ./configure option that
I've missed?
Thanks in advance for any help,
Richard
RS> #include <wx/longlong.h>
RS> #include <wx/string.h>
RS>
RS> int main() {
RS> wxLongLong id;
RS> wxString::Format( "%lld", id );
RS> }
RS>
RS> There's lot of code like this in the application, and it
RS> apparently compiles fine with Microsoft Visual C++ (not sure
RS> which version as I don't have a copy of Windows to try it),
RS> but it won't compile with either gcc 4.4.3 or gcc 4.6.0
RS> using either wxWidgets 2.9.1 or 2.8.10. See below for the
RS> output of the compilation.
The code above is indeed invalid and MSVC only compiles it because of
a non-standard extension that was apparently added to it specifically to
allow broken MFC programs to use CString::Format("%s", CString).
RS> I can fix it by changing id to id.GetValue(), but this would
RS> be a very intrusive change to the code base
Another possibility would be to use wxLongLong_t instead of wxLongLong.
The former is just a typedef for __int64 or "long long", depending on
platform/compiler, and so is a primitive type. wxLongLong was needed
because 15 years ago there were some platforms without a native 64 bit type
but I don't think they still exist so using wxLongLong_t should be fine
from portability point of view.
RS> -- the construct
RS> appeals getting on for a thousand times -- and there's no
RS> guarantee the patch would be accepted upstream. It's clear
RS> that wxString::Format can handle some non-POD-types, so I'm
RS> hoping it can handle wxLongLong too, especially as it seems
RS> to work with Visual C++.
It should be possible to extend wxArgNormalizer to deal with this in wx 2.9
but this wouldn't be trivial so while we'd accept a patch for this if you
submit one, I really don't think it's going to happen otherwise. And for
2.8 this can't be done at all.
Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Vadim Zeitlin wrote:
> On Fri, 13 May 2011 22:41:19 +0100 (BST) Richard Smith <ric...@ex-parrot.com> wrote:
>
> RS> #include <wx/longlong.h>
> RS> #include <wx/string.h>
> RS>
> RS> int main() {
> RS> wxLongLong id;
> RS> wxString::Format( "%lld", id );
> RS> }
>
> The code above is indeed invalid and MSVC only compiles it because of
> a non-standard extension that was apparently added to it specifically to
> allow broken MFC programs to use CString::Format("%s", CString).
OK, that figures.
> It should be possible to extend wxArgNormalizer to deal with this in wx 2.9
> but this wouldn't be trivial so while we'd accept a patch for this if you
> submit one, I really don't think it's going to happen otherwise. And for
> 2.8 this can't be done at all.
I think the following does the job:
template<>
struct wxArgNormalizer<wxLongLong>
{
wxArgNormalizer(wxLongLong value,
const wxFormatString *fmt, unsigned index)
: m_value(value)
{
wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_LongLongInt );
}
wxLongLong_t get() const { return m_value.GetValue(); }
wxLongLong m_value;
};
Tested in 2.9.1. Might it be possible to include something
along these lines in a future version?
Meanwhile, if I omit the wxASSERT_ARG_TYPE, I can add
this to a suitably global header in the project I'm porting
and it all works.
Thanks for your help.
Richard
RS> I think the following does the job:
RS>
RS> template<>
RS> struct wxArgNormalizer<wxLongLong>
RS> {
RS> wxArgNormalizer(wxLongLong value,
RS> const wxFormatString *fmt, unsigned index)
RS> : m_value(value)
RS> {
RS> wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_LongLongInt );
RS> }
RS>
RS> wxLongLong_t get() const { return m_value.GetValue(); }
RS>
RS> wxLongLong m_value;
RS> };
RS>
RS> Tested in 2.9.1. Might it be possible to include something
RS> along these lines in a future version?
I've tried this but it doesn't work for me because of a circular
dependency between wx/strvararg.h and wx/longlong.h: the latter includes
wx/string.h which includes the former, but the former now needs to include
the latter to get wxLongLong declaration. So wxLongLong type is not defined
when the template specialization is parsed.
Where exactly did you put it to make it work? I guess it could go into
wx/longlong.h itself but then wxASSERT_ARG_TYPE can't be used because it's
undefined in wx/strvararg.h and so this would need to be refactored
somehow.
If you could please post (or put on Trac) a proper patch (please see
http://trac.wxwidgets.org/wiki/HowToSubmitPatches) with your changes, it
would be great.
Thanks,
I placed it at the end of wx/longlong.h, and removed the
#undef of wxASSERT_ARG_TYPE in wx/strvararg.h. The macros
has a sensible enough name that I can't see if clashing with
anything in user code, so leaving it defined should be
harmless enough.
As to exactly where in wx/longlong.h the specialisation
belongs, I'm not sure, as I must admit I'm a little sketchy
on precisely when wxLongLongWx and wxLongLongNative are
used. If it's possible for both to be used, I guess both
should have their own specialisations. Similarly, the
wxULongLong{Wx,Native} types.
Richard
RS> I placed it at the end of wx/longlong.h, and removed the
RS> #undef of wxASSERT_ARG_TYPE in wx/strvararg.h.
Ok, yes, I see that this should work. I've uploaded my patch to
http://review.bakefile.org/r/268/ and will commit it if there are no
comments/objections soon.
RS> As to exactly where in wx/longlong.h the specialisation
RS> belongs, I'm not sure, as I must admit I'm a little sketchy
RS> on precisely when wxLongLongWx and wxLongLongNative are
RS> used. If it's possible for both to be used, I guess both
RS> should have their own specialisations. Similarly, the
RS> wxULongLong{Wx,Native} types.
It's possible for both to be used but this is only useful for testing so I
don't think we need to complicate things by specializing wxArgNormalizer
for both of them, just the simple patch above should be enough for normal
use.
Regards,
> On Mon, 16 May 2011 01:34:01 +0100 (BST) Richard Smith <ric...@ex-parrot.com> wrote:
>
> RS> I placed it at the end of wx/longlong.h, and removed the
> RS> #undef of wxASSERT_ARG_TYPE in wx/strvararg.h.
>
> Ok, yes, I see that this should work. I've uploaded my patch to
> http://review.bakefile.org/r/268/ and will commit it if there are no
> comments/objections soon.
Looks good and works for me.
Many thanks,
Richard