I'm having some trouble compiling code that uses std::lower_bound on systems with newer versions of gcc. From my tests, 4.1 works, but 4.6 fails.
Here is the relevant code snippet:
template <typename RandomAccessIterator, typename Value, typename Comparer>
int my_binary_search(RandomAccessIterator const first, RandomAccessIterator const last, Value const& value, Comparer comparer)
{
RandomAccessIterator it(std::lower_bound(first, last, value, comparer));
//some more code below
}
The error I am seeing is:
error: no matching function for call to ‘lower_bound(const __gnu_cxx::__normal_iterator<int*, std::vector<int> >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int> >&, const int&, bool (*&)(int, int))’
testing.h:37:75: note: candidate is:
/usr/include/c++/4.6/bits/stl_algobase.h:936:5: note: template<class _ForwardIterator, class _Tp> _ForwardIterator std::lower_bound(_ForwardIterator, _ForwardIterator, const _Tp&)
Does anybody have ideas on how to fix this?
For anyone finding this on google:
I had the same issue
Includes were "functional" and "list", didnt give me any error lower_bound wasnt defined or anything, just that it couldnt find a matching function.
Including "algorithm" did the trick.. nearly an hour of searching around for such a stupid thing
Related
I'm trying to create a struct template with a variadic template type pack, that can deduct the sum of the size of all types passed in.
Below you find a simplified example, in the real-world context, the size computed is used to create further member objects.
template <typename... Types>
struct OverallSize
{
template <typename FirstType, typename... NextTypes>
static constexpr size_t sizesum() { return sizeof (FirstType) + sizesum<NextTypes...>(); }
template <typename LastType>
static constexpr size_t sizesum() { return sizeof (LastType); }
static constexpr size_t size = sizesum<Types...>();
};
// Should work e.g. like this
auto s = OverallSize<int, float, char>::size; // s will be 9 on x86-64
I'm used to this recursive parameter unpacking approach when it comes to argument lists and assumed this works as well with argument-less functions and explicit template specification. However I get the following error when compiling with clang
Call to 'sizesum' is ambiguous
...
Candidate function [with FirstType = unsigned long, NextTypes = <>]
Candidate function [with LastType = unsigned long]
So it seems as if the last recursion iteration doesn't work here – not sure why the compiler doesn't simply chose the most obvious choice: The one with only one template type – just as it would happen if there was an actual template argument passed to the function.
So, what do I have to do to make this compile and work as desired?
For C++14 you can use SFINAE:
template <
typename FirstType,
typename... NextTypes,
std::enable_if_t<sizeof...(NextTypes) >= 1>* = nullptr >
static constexpr size_t sizesum() {
return sizeof (FirstType) + sizesum<NextTypes...>();
}
this template will be considered only if parameters pack has size >= 1.
Demo
For a given usage
template<typename T1>
class node{
public:
using sp2node = shared_ptr<node<T1>>;
using r_sp2node = shared_ptr<node<T1>>&;
public:
r_sp2Node getN();
private:
sp2node N;
};
(1)
template<typename T1> decltype(node<T1>::r_sp2node) node<T1>::getN(){
return N;
}
(2)
template<typename T1> typename node<T1>::r_sp2node node<T1>::getN(){
return N;
}
(1) generates the compiler error:
error: missing 'typename' prior to dependent type name
'node<T1>::r_sp2node'
whereas (2) compiles
Can someonene explain what is the difference between the above two?
There are two things wrong with the first example.
In decltype(node<T1>::r_sp2node), reading inside out, the compiler first needs to know what node<T1>::r_sp2node. Is it a type, or something else? This is why the typename disambiguator exists, and that is what the error message is all about.
The second problem is that decltype expects some expression, not a type. So even if you used typename, it still wouldn't compile. (As a simple example, decltype(int) won't even compile.)
To answer the question specifically, the difference between the two is that the first is not valid C++ and the second is the way to go.
In a very simple situation with a constrained constructor, testing for convertibility of the argument, an error is produced in clang, but not in g++:
#include <type_traits>
template <class T, class U>
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
template <class T>
struct A
{
template <class S, class = std::enable_if_t<Convertible<S,T>> >
A(S const&) {}
};
int main()
{
A<double> s = 1.0;
}
Maybe this issue is related to Is clang's c++11 support reliable?
The error clang gives, reads:
error: no member named 'value' in 'std::is_convertible<double, A<double> >'
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
I've tried
g++-5.4, g++-6.2 (no error)
clang++-3.5, clang++-3.8, clang++-3.9 (error)
with argument -std=c++1y and for clang either with -stdlib=libstdc++ or -stdlib=libc++.
Which compiler is correct? Is it a bug in clang or gcc? Or is the behavior for some reasons undefined and thus both compilers correct?
First of all, note that it works fine if you use:
A<double> s{1.0};
Instead, the error comes from the fact that you are doing this:
A<double> s = 1.0;
Consider the line below (extracted from the definition of Convertible):
std::is_convertible<U,T>::value
In your case, this is seen as it follows (once substitution has been performed):
std::is_convertible<double, A<double>>::value
The compiler says this clearly in the error message.
This is because a temporary A<double> is constructed from 1.0, then it is assigned to s.
Note that in your class template you have defined a (more or less) catch-all constructor, so a const A<double> & is accepted as well.
Moreover, remember that a temporary binds to a const reference.
That said, the error happens because in the context of the std::enable_if_t we have that A<double> is an incomplete type and from the standard we have this for std::is_convertible:
From and To shall be complete types [...]
See here for the working draft.
Because of that, I would say that it's an undefined behavior.
As a suggestion, you don't need to use std::enable_if_t in this case.
You don't have a set of functions from which to pick the best one up in your example.
A static_assert is just fine and error messages are nicer:
template <class S>
A(S const&) { static_assert(Convertible<S,T>, "!"); }
I distilled the code and ended up with the one below. Error is when inserting into a map...
Thanks to the person who marked down the question - hopefully he will be the first to answer it ;).
Seriously now, my point is: the fact that move is done on a "best effort" basis and that one cannot ensure it is used (as here with a naive delete) makes room for a lot of confusion. To me it's dodgy one has to provide a never used copy constructor body just to silence the compiler.
Of course, may be a bad play between the compiler and my stl. Leaving the people who live and breathe the C++ standard to clarify.
#include <vector>
#include <map>
#include <iostream>
using namespace std;
struct FeedDataType
{
FeedDataType() {};
FeedDataType(FeedDataType&& ) = default;
#if 0
// error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&) - why?
FeedDataType(const FeedDataType& ) = delete;
#else
// Compiles ok but never called. But cannot mark it delete...
FeedDataType(const FeedDataType& ) { cout << "Never called!" << endl; };
#endif
};
int main ()
{
vector< FeedDataType > x;
map<int, vector< FeedDataType > > mymap;
mymap.insert( std::make_pair( 0, x ) );
}
Error:
In file included from /cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/vector:63:0,
from play3.cpp:1:
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = FeedDataType; _Args = {const FeedDataType&}]':
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; bool _TrivialValueTypes = false]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; _Tp = FeedDataType]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:310:9: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = FeedDataType; _Alloc = std::allocator<FeedDataType>; std::vector<_Tp, _Alloc> = std::vector<FeedDataType>]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:137:64: required from 'constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = int; _U2 = std::vector<FeedDataType>&; <template-parameter-2-3> = void; _T1 = int; _T2 = std::vector<FeedDataType>]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:273:72: required from 'constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = std::vector<FeedDataType>&; typename std::__decay_and_strip<_T2>::__type = std::vector<FeedDataType>; typename std::__decay_and_strip<_T1>::__type = int]'
play3.cpp:24:44: required from here
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)'
play3.cpp:13:9: error: declared here
ORIGINAL POST:
There is a compiler error (g++ 4.7.2 on RedHat) I'd like to clarify.
What is all about: simply want to enforce the use of the move constructor only.
So I write:
FeedDataType(FeedDataType&& ) = default;
FeedDataType(const FeedDataType& ) = delete;
Alas, it doesn't compile (I'll spare you the full stack trace):
.../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)'
Not being obvious where copy ctor required, I write a body for it to let the program core when used and then look at the stack trace:
FeedDataType(FeedDataType&& ) = default;
FeedDataType(const FeedDataType& ) { cerr << "Called" << endl; assert(false); }
Well, the program compiles and runs without entering the copy ctor code. So, if not used, why cannot the copy ctor be deleted? How can one be sure of what is being used?
Other thing that I don't get:
void FeedData::add( const FeedDataType & feedDataRow )
{
// Is move used here? If not why not warn?
some_vector.push_back( std::move(feedDataRow) );
}
This apparently uses the copy constructor. Would have been good having a warning/error from the compiler that move construction was not in use here? In large programs it would be easy to miss the const and believe that std::move would do the job. In fact, should have been a compiler error - feedDataRow is const, move construction from it should not be possible?
Using non-const reference appears to be better as the move constructor is used in that case. Or should one pass here by value?
I think the first issue is a compiler bug, but would like to be enlightened by someone who knows what was going on. I was thinking move semantics is easy but obviously need to do my homework. Looking for Mr. Meyers books on C++11 ;).
Thanks,
Adrian
Well, the program compiles and runs without entering the copy ctor code.
So, if not used, why cannot the copy ctor be deleted?
How can one be sure of what is being used?
It may be in a scope where it may be use
in the following code:
void foo() = delete;
void bar(bool b)
{
if (b) { foo(); }
// Other stuff
}
Suppose that we call only bar(false), foo is not called, but bar use a deleted function anyway.
If you follow the error link, you will see in which part of code Copy Constructor may be used.
std::move means, approximately, "move if you can, otherwise copy" (not quite, but close enough for purposes of this discussion). It does not mean "move if you can, otherwise panic". The former semantics is useful most everywhere, including virtually all situations of writing template-based generic components. The latter is only useful in rare cases when moving might be impossible, and copying might be possible, but you don't want to copy.
The standard gives you the former semantics but not the latter. If you need the latter, you can write your own along these lines:
template< class T >
typename std::remove_reference<T>::type&& my_move( T&& t )
{
return static_cast<typename std::remove_reference<T>::type&&>(t);
}
template< class T >
typename std::remove_reference<T>::type&& my_move( const T& t )
{
static_assert(!std::is_lvalue_reference<T&>::value, "Move is requested, but only copying is possible");
}
The copy constructor is used by the copy constructor of vector, which is used by the constructor of std::pair called in std::make_pair. The reason it's not actually called in a given run of your little example program is that the vector is empty.
Try std::move on the x when you call make_pair.
I have a class called RenderCommand:
class RenderCommand
{
public:
RenderCommandType commandType;
RenderCommand() : commandType(RenderCommandTypeNone) {};
virtual ~RenderCommand() {};
};
I then have a queue of these RenderCommands which stores unique_ptrs to them:
typedef std::deque<std::unique_ptr<RenderCommand>> RenderQueue;
Finally in a section of code, I create a vector of these RenderQueues, and try to resize it:
std::vector<RenderQueue> queues;
queues.resize(4);
The resize line is giving me a few issues. In clang I get the error message:
call to deleted constructor of 'std::unique_ptr<RenderCommand, std::default_delete<RenderCommand> >'
With GCC 4.8, I just get a whole bunch of errors similar to
required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::_Deque_iterator<std::unique_ptr<RenderCommand>, const std::unique_ptr<RenderCommand>&, const std::unique_ptr<RenderCommand>*>; _ForwardIterator = std::_Deque_iterator<std::unique_ptr<RenderCommand>, std::unique_ptr<RenderCommand>&, std::unique_ptr<RenderCommand>*>; _Tp = std::unique_ptr<RenderCommand>]'
This compiles fine in Visual Studio 2012 however so I'm a little lost. I appreciate any help you guys can give!
EDIT: RenderCommandType is just an enum:
enum RenderCommandType
{
RenderCommandTypeNone = 0,
RenderCommandTypeBeginRepeat,
RenderCommandTypeEndRepeat,
RenderCommandTypeBeginScene,
RenderCommandTypeEndScene,
//etc
};
EDIT2: Ok this seems to be a std::deque problem, changing RenderQueue to:
typedef std::vector<std::unique_ptr<RenderCommand>> RenderQueue;
works. Also removing references to my own class and just using an int still doesn't work (unless like above I replace deque with vector):
std::vector<std::deque<std::unique_ptr<int>>> tempQueue;
tempQueue.resize(4);
:-/
I simplified your example to
#include <deque>
#include <vector>
struct A {
A(const A&) = delete;
};
void f()
{
std::vector<std::deque<A> > q;
q.resize(4);
}
With g++ 4.6, this example compiles fine. From g++ 4.7 on however, it prints a lot of error messages, finally resulting in the mentioned
error: use of deleted function ‘A::A(const A&)’
Replacing deque with vector or list doesn't show this behaviour.
So, it seems this is either a regression from g++ 4.6 to 4.7 or a correction of a previous bug. In any case, I filed a bug report with g++, see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59192