Error: function template already inherited - with icpc - c++11

I am writing a class that inherits from std::vector (*) and I want to be able to construct it in all the ways that are available for its base, so I use
#include <vector>
struct B : public std::vector<double>
{
using std::vector<double>::vector;
};
This compiles fine with the g++ and clang, but the Intel compiler gives me (with flag -std=c++11)
error: function template "B::B(_ForwardIterator, _ForwardIterator, const std::__1::allocator<double> &)" already inherited from "std::__1::vector<double, std::__1::allocator<double>>"
at the using directive.
Any ideas why this is happening and/or how to solve it?
Update: it would seem this is OS dependent, works fine on Linux and Windows platforms but fails on OS X. A discussion is ongoing on the Intel forums.
(*) I don't want to use polymorphism, please avoid "this is bad practice" answers if not directly relevant - there are in fact numerous posts that agree this is acceptable.

Related

Exploring c++ forward declarations of nested types and a standards compliance teaser?

I recently, thanks to awesome Jan 9th 2018 planet clang team work and others great articles, figured out how to configure my dev-setup to integrate llvm 7.0, visual studio 2017 15.5.6 for 32-bit and 64-bit Intel architecture.
My motivation for this was forced by Microsoft's 15.4.X breaking std lib framework changes that rendered the Microsoft experimental clang c2 front end (somewhat buggy anyway) to break.
In the Intel setup I use LLVM tools to both compile and link PDB debuggable Windows code.
See other posts I made on that topic for instructions on how to integrate everything so you can use latest updates to Visual Studio 2017 tools and debugging with latest 7.X builds of LLVM/clang. For those interested in full Windows 10 on ARM development (not UWP sillyness), I am separately still working the same setup for arm-32, arm-64 to all work together using LLVM tools as well as use Wine-ARM for Linux.
Once done with that integration, I was looking to see what LLVM 7.0 clang allowed to be done without needing P0289R0 Forward declarations of nested classes.
struct ds1; struct ds1::ds2;
I started fiddling around and wrote the sample below. It compiles and runs correctly with clang-llvm 7.0. It will not compile (without errors) when using Microsoft's latest c++ front-ends.
So, I scratched my head wondering if it is actually legal c++ code. I often do that, as I use c++ in non-standard style with templates and forward references. For example, I only use one cpp file per module and use includes within templates to minimize any forward declarations. That pattern avoids the need for makefiles and dramatically improves portability, compilation time, and often code generation quality. In effect, I use the .cpp file as a makefile with minimal to no macros and pure clang/gcc and c++ features.
In asking myself if the code was actually legit c++ according to the standard, I re-read through standard. I concluded that yes it was standard compliant to template rules, but that would make Microsoft's compiler be non-compliant. So I wondered if others more knowledgeable might chime in and clarify the question.
Here is the code sample:
(note it happens to also be intentionally infinitely recursive in a number of ways to test compiler detection)
// P0289R0 clang Forward declarations of nested classes
//- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0289r0.pdf
// struct ds1; struct ds1::ds2;
struct nested1;
struct nested2;
// Code that references "nested1" here (could be pointer, but in template model this is more interesting case)
template <bool f_ta = true>
void foo(nested1& n1) {
n1.run();
}
template <bool f_ta = true>
struct outer {
struct inner {
void run() {
nested1 n1; nested2 n2;
n2.test();
foo(n1);
}
};
void test() {
nested1 n1;
foo(n1);
}
};
//using nested = outer::inner; // Must be defined at module-scope
//typedef outer::inner nested; // Must be defined at module-scope
struct nested1 : outer<>::inner { using super_t = outer<>::inner; using super_t::super_t; };
struct nested2 : outer<> { using super_t = outer<>; using super_t::super_t; };
bool fAutoRunIt = []() {
nested2 a;
a.test();
return true;
}();
You can easily modify the example to not be recursive and still test out the other forward reference behavior.
Cheers, David

Storing pairs in a GCC rope with c++11

I'm using a GCC extension rope to store pairs of objects in my program and am running into some C++11 related trouble. The following compiles under C++98
#include <ext/rope>
typedef std::pair<int, int> std_pair;
int main()
{
__gnu_cxx::rope<std_pair> r;
}
but not with C++11 under G++ 4.8.2 or 4.8.3.
What happens is that the uninitialised_copy_n algorithm is pulled in from two places, the ext/memory and the C++11 version of the memory header. The gnu_cxx namespace is pulled in by rope and the std namespace is pulled in by pair and there are now two identically defined methods in scope leading to a compile error.
I assume this is a bug in a weird use case for a rarely used library but what would be the correct fix? You can't remove the function from ext/memory to avoid breaking existing code and it now required to be in std. I've worked around it using my own pair class but how should this be fixed properly?
If changing the libstdc++ headers is an option (and I asked in the comments whether you were looking for a way to fix it in libstdc++, or work around it in your program), then the simple solution, to me, seems to be to make sure there is only one uninitialized_copy_n function. ext/memory already includes <memory>, which provides std::uninitialized_copy_n. So instead of defining __gnu_cxx::uninitialized_copy_n, it can have using std::uninitialized_copy_n; inside the __gnu_cxx namespace. It can even conditionalize this on C++11 support, so that pre-C++11 code gets the custom implementation of those functions, and C++11 code gets the std implementation of those functions.
This way, code that attempts to use __gnu_cxx::uninitialized_copy_n, whether directly or through ADL, will continue to work, but there is no ambiguity between std::uninitialized_copy_n and __gnu_cxx::uninitialized_copy_n, because they are the very same function.

Error: functions that differ only in their return type cannot be overloaded

I'm using mac os 10.9, I have a C++ program that uses freeglut library. When I try to make the project. It gives an error which I don't know if it's my fault or not. This is the message:
In file included from /usr/X11/include/GL/freeglut.h:18:
/usr/X11/include/GL/freeglut_ext.h:177:27: error: functions that differ only in their return type cannot be overloaded
FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName );
More information: I used CMake (version 2.8.12) to generate the Makefile, and installed the latest version of Xcode and XQuartz.
Any help is appreciated. Thank you.
In glut.h and freeglut_ext.h files:
In glut.h:
#if (GLUT_API_VERSION >= 5)
extern void * APIENTRY glutGetProcAddress(const char *procName) OPENGL_DEPRECATED(10_3, 10_9);
#endif
In freeglut_ext.h:
/*
* Extension functions, see freeglut_ext.c
*/
typedef void (*GLUTproc)();
FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName );
One of the declarations returns a function type GLUTproc (specifying a function that takes no arguments), and the other declaration returns a pointer (void*). Both functions take the same arguments (a single const char*). What the compiler says is true.
You're only seeing a complaint about "overloading" because it's C++. In C++, if a compiler thinks it's seen two different functions with the same name then each one needs to have different arguments (e.g. a different number of arguments, or distinct types).
In this case, I doubt the functions are meant to be different; they're meant to be the same, and at some point the API evolved and changed the declaration.
You need to find some way to prevent the compiler from seeing both declarations at the same time (perhaps by setting GLUT_API_VERSION). If you have to, you can #include just one of the files and see if you really need the other file (and if you did, you may have to manually declare some things to avoid a 2nd #include).

What to do if tgamma() function is not defined?

I am trying to use tgamma() from the standard library. When I try to compile, I get the error message:
Call to undefined function tgamma
I have the directive #include <cmath>. I use Embarcadero C++ Builder XE3, which claims to support C++11 standards. What could be my problem, and how to fix it?
Boost contains a tgamma function.
#include <boost/math/special_functions/gamma.hpp>
...
double rootPi = boost::math::tgamma<double>(0.5);
Of course, you can always switch to a different compiler, like gcc.

Boost.asio compilation problem: undefined reference to `__sync_add_and_fetch_8

Hey guys,
This could be a noob question, but I really can't find any useful solution through Google.
I'm testing a hello world with boost.asio, the program is quite simple:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello, world!\n";
return 0;
}
I passed the compilation and run well on my Intel Pentium PC (Ubuntu 10.10, gcc 4.4.5, Boost 1.46.0). The command line I used was
g++ -o a a.cpp -I /Boost-Include-Path/ -L /Boost-lib-Path/ -lboost_system
But when I compile the same code on another machine(which is a big one, I'll explain it later), it can't pass the compilation and gives such errors:
/tmp/ccOZxZBX.o: In function boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()': a.cpp:(.text._ZN5boost4asio6detail21gcc_sync_fenced_blockC1Ev[boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()]+0x4c): undefined reference to__sync_lock_test_and_set_4' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator++()': a.cpp:(.text._ZN5boost6detail12atomic_countppEv[boost::detail::atomic_count::operator++()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator--()': a.cpp:(.text._ZN5boost6detail12atomic_countmmEv[boost::detail::atomic_count::operator--()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator long() const': a.cpp:(.text._ZNK5boost6detail12atomic_countcvlEv[boost::detail::atomic_count::operator long() const]+0x30): undefined reference to__sync_fetch_and_add_8'
The machine I used was a SiCortex SC5832,which use MIPS64 instruction set processors, OS is changed CentoOS. Gcc 4.2.3, Boost1.46.0. Is it possible that there are problems about the compatibility of the MIPS? I added -mips64 option, but it still give the same errors.
I know this environment could not be very usual, but I think some people who are using similar big machines may face the same problem.
Any help would be appreciated. By the way, I don't have sudo permission.
Thanks,
Tony
This function is a GCC built-in function, and it was introduced around GCC 4.2 (iirc) see documentation.
According to the documentation it's not available on all target processors.
If you look at boost/smart_ptr/detail/atomic_count.hpp it looks like it would fall into the #elif defined(BOOST_SP_HAS_SYNC) block. i.e. boost/smart_ptr/detail/atomic_count_sync.hpp.
Support for this is determined in boost/smart_ptr/detail/sp_has_sync.hpp. This header essentially assumes that GCC supports this on all platforms except for a few exceptions. You might want to insert MIPS as another exception here and submit a patch to boost.
You'll also see that one workaround is to define BOOST_AC_USE_PTHREADS. This will use a mutex around the atomic count, which probably is significantly less efficient, but at least it will work until you can figure out what atomic operations are supported on MIPS64.

Resources