Error while compilation of std::map with boost::shared_ptr - boost

I am trying to compile my code in vs2005.
I am using std::map and boost::shared_ptr (v1.47.0)
My code looks something like this
struct B {
int a;
}
typedef boost::shared_ptr<B> K;
std::map<const std::string, K > mymap;
//some code
std::map<const std::string, K >::iterator it;
for (it = mymap.begin(); it < mymap.end(); it++ )
{
//do something
}
The compiler is giving an error at the for statement.
The following is the error
error C2784: 'bool boost::operator <(const boost::intrusive_ptr &,const boost::intrusive_ptr &)' : could not deduce template argument for 'const boost::intrusive_ptr &' from 'std::_Tree<_Traits>::iterator'.
Any help is appreciated.
Thank you.

You are using the wrong operator for the checking against mymap.end(). Change the loop to
for (it = mymap.begin(); it != mymap.end(); it++ )

Related

Failed to compile OpenVDB on Windows(VS2017)

I tried to compile OpenVDB on Windows11(VS2017), but confusing error occurs:
Error C2676 Binary '<': 'const _Ty' does not define the operator or a conversion to a type that can be received by a predefined operator openvdb_shared
Error C2056 invalid expressions
Error C2088 invalid for class
It points to <algorithm.h> file, line 5386: "_NOEXCEPT_COND(_NOEXCEPT_OPER(_Left < _Right))".
#pragma warning(push)
#pragma warning(disable: 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type)
template<class _Ty>
_Post_equal_to_(_Left < _Right ? _Right : _Left)
_NODISCARD constexpr const _Ty& (max)(const _Ty& _Left, const _Ty& _Right)
_NOEXCEPT_COND(_NOEXCEPT_OPER(_Left < _Right))
{ // return larger of _Left and _Right
if (_Left < _Right)
{
_STL_ASSERT(!(_Right < _Left), "invalid comparator");
return (_Right);
}
return (_Left);
}
and anothor fatal error:
fatal error LNK1104: can not open file “....\openvdb\openvdb\Debug\openvdb.lib”
I download OpenVDB source code and dependencies by git and vcpkg following the manual OpenVDB. I have no idea about how to fix those problems. Any suggestions or solution would be greatly appreciated!!!

SFINAE expression fails to compile with clang

This looks like an issue in clang (I've already opened a bug here), but I'd like to be sure that I'm not doing a mistake.
Consider the following code:
#include <type_traits>
#include <cstddef>
template<std::size_t N, std::size_t M, std::enable_if_t<not (N>M)>* = nullptr> // (1)
struct S: public S<N+1, M> { };
template<std::size_t N>
struct S<N, N> { };
int main() {
S<0, 1> c{};
}
It fails to compile with the following error:
8 : error: non-type template argument specializes a template parameter with dependent type 'std::enable_if_t M)> *' (aka 'typename enable_if M), void>::type *')
struct S { };
The same code works as expected using the following line instead of (1):
template<std::size_t N, std::size_t M, typename = std::enable_if_t<not (N>M)>>
The SFINAE expression is almost the same. It is based on a specialization of std::enable_if_t and I would expect the same result (success or failure) for both of the examples.
Are my expectations wrong?
Note that GCC works fine in either cases.
I think this is a gcc bug actually, as a result of [temp.class.spec]:
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
specialization. [ Example:
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
—end example ]
In your example, the type of the 3rd template parameter is dependent on a parameter. When you swap it to typename = std::enable_if_t<...>, then this rule no longer applies.
Note: is there any reason to use SFINAE here anyway, as opposed to static_assert-ing?

Issue with the templatized version of insertion sort

Below is the templatized version of insertion sort which results in compilation errors to perform insertion sort in place without any extra space.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T>
insertSort(T start, T end)
{
typename std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
TmpVec tmp(std::make_move_iterator(start), std::make_move_iterator(end));
TmpVec::iterator begin = std::begin(tmp);
TmpVec::iterator end = std::end(tmp);
for(TmpVec::iterator i = begin; i != end; i++)
{
typename std::iterator_traits<T>::value_type value = *i;
TmpVec::iterator pos = i;
while (pos > start && *(pos-1) > value)
{
*pos = std::move(*(pos-1));
--pos;
}
*pos = value;
}
}
int main(int argc, char** argv) {
std::vector<double> arr = {1,5,3,2,6,3,9,8};
insertSort<double>(arr.begin(), arr.end());
for(int i=0; i<arr.size(); i++)
{
std::cout << arr[i] << " ";
}
return 0;
}
I am compiling this with the following compilation line.
g++ -std=c++11 -c -g -MMD -MP -MF "build/Debug/MinGW-Windows/main.o.d" -o build/Debug/MinGW-Windows/main.o main.cpp
This yields the following errors.
main.cpp: In function 'int insertSort(T, T)':
main.cpp:21:12: error: expected ';' before 'tmp'
TmpVec tmp(std::make_move_iterator(start), std::make_move_iterator(end));
^
main.cpp:22:5: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator begin = std::begin(tmp);
^
main.cpp:23:5: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator end = std::end(tmp);
^
main.cpp:24:9: error: 'TmpVec' is not a class, namespace, or enumeration
for(TmpVec::iterator i = begin; i != end; i++)
^
main.cpp:24:37: error: 'i' was not declared in this scope
for(TmpVec::iterator i = begin; i != end; i++)
^
main.cpp:27:9: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator pos = i;
^
main.cpp:28:16: error: 'pos' was not declared in this scope
while (pos > start && *(pos-1) > value)
^
main.cpp:33:10: error: 'pos' was not declared in this scope
*pos = value;
^
main.cpp: In function 'int main(int, char**)':
main.cpp:40:46: error: no matching function for call to 'insertSort(std::vector<double>::iterator, std::vector<double>::iterator)'
insertSort<double>(arr.begin(), arr.end());
^
main.cpp:40:46: note: candidate is:
main.cpp:18:1: note: template<class T> int insertSort(T, T)
insertSort(T start, T end)
^
main.cpp:18:1: note: template argument deduction/substitution failed:
main.cpp:40:46: note: cannot convert 'arr.std::vector<_Tp, _Alloc>::begin<double, std::allocator<double> >()' (type 'std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}') to type 'double'
insertSort<double>(arr.begin(), arr.end());
Kindly help in solving the above issue.
typename std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
this states std::vector<typename std::iterator_traits<T>::value_type> is a typename. A compiler should issue a warning/error, because the typename is redundant.
It then declares a variable TmpVec of that type.
Every use after that uses TmpVec as if it was a type, not a variable.
You probably want
typedef std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
I'd also advise
using tmp_iterator = typename TmpVec::iterator;
and using tmp_iterator as a type instead of TmpVec::iterator.

C++11 Variadic function in variadic template class not working as expected

Sincere apologies if this has been answered elsewhere, I did search but couldn't find a clear match.
I have a variadic function in a template class that does not work exactly as I expected. I have a workaround, but I suspect it's not the best solution.
Consider the following code:
#include <iostream>
#include <functional>
#include <vector>
template< typename... ARGS >
class Kitten
{
public:
using Callback = std::function< void( ARGS&&... ) >;
Kitten() = default;
void addCallback( Callback && c )
{
callbacks.push_back( std::forward< Callback >( c ) );
}
void processCallbacks( ARGS &&... args )
{
for ( Callback const &c : callbacks )
{
c( std::forward< ARGS >( args )... );
}
}
private:
std::vector< Callback > callbacks;
};
int main( int argc, const char * argv[] )
{
( void ) argc;
( void ) argv;
Kitten<int, float> kitty;
kitty.addCallback( []( int i, float f )
{
std::cout << "Int: " << i << "\nFloat: " << f << "\n";
} );
kitty.processCallbacks( 2, 3.141f );
int ii = 54;
float ff = 2.13f;
kitty.processCallbacks( ii, ff );
return 0;
}
This will not compile, the second call to processCallbacks will generate an error (clang, similar issue seen on vc14).
I can fix the compilation and get things working as expected if I change the definition of processCallbacks to:
template< typename... FORCEIT >
void processCallbacks( FORCEIT &&... args )
{
for ( Callback const &c : callbacks )
{
c( std::forward< ARGS >( args )... );
}
}
It seems to me to be a bit of a cheesy workaround even if it seems to work, and I suspect I'm missing a better solution.
My understanding of why the first sample fails is because there's no type deduction being done on the argument pack, so the compiler isn't generating the correct code for all cases. The second sample works because it forces the type deduction on the argument pack.
It's been puzzling me for a while on and off. Any help much appreciated.
edit: vc12 compiler error:
error C2664: 'void Kitten<int,float>::processCallbacks(int &&,float &&)' : cannot convert argument 1 from 'int' to 'int &&'
edit: Apple LLVM version 7.0.0 compiler error:
error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'
Regarding the change suggested in the comments to use std::move, addCallback would seem to be even more flexible in the form:
template< typename FUNCTION >
void addCallback( FUNCTION && c )
{
callbacks.emplace_back( std::forward< FUNCTION >( c ) );
}
Using std::forward because the function now takes a universal reference.
As this would allow the following to work:
std::function< void( int, float )> banana( []( int i, float f )
{
std::cout << "Int: " << i << "\nFloat: " << f << "\n";
} );
kitty.addCallback( banana );
void processCallbacks( ARGS &&... args )
{
//...
}
For each type in ARGS the allowed value categories will be set by the template arguments to Kitten. E.g. for Kitten<float, int&, const bool&>, processCallbacks will accept rvalues for the first parameter, lvalues for the second (due to reference collapsing rules) and both for the third (because rvalues can bind to const lvalue references). This will not give you perfect forwarding.
template< typename... FORCEIT >
void processCallbacks( FORCEIT &&... args )
{
//...
}
That function template accepts both lvalues and rvalues because there is type deduction. Such a parameter is known as a forwarding reference parameter. Forwarding reference parameters must be of the form T&&, where T is some deduced template parameter.
If you want to accept lvalues and rvalues and perfect-forward them, you should use the latter form. Although it might seem weird to you at first, this is a fairly common pattern.

differnt behaviour between clang and microsoft c++/QT5 with constructors and return values

According to microsoft visual studio 2013 (being built from QT creator, QT 5.4), this code is fine:
#include <string>
struct X {
X(std::string const &) {};
};
X wibble() { return ""; }
clang however says
test.cpp(53) : error: no viable conversion from 'const char [1]' to 'X'
X wibble() { return ""; }
test.cpp(49) : note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [1]' to 'const X &' for 1st argument
struct X {
test.cpp(49) : note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [1]' to 'X &&' for 1st argument
struct X {
test.cpp(50) : note: candidate constructor not viable: no known conversion from 'const char [1]' to 'const std::string &' (aka 'const basic_string<char, char_traits<char>, allocator<char> > &') for 1st argument
X(std::string const &) {};
It does the same thing with QString for what it's worth. Assuming clang is correct, why is it complaining?
It doesn't compile even in MinGW, because it is illegal. Because only one level of user-defined implicit conversion is legal. In your code you have 2 level conversion: to std::string and to X.
struct X {
X( std::string const &) {}
};
X wibble1() { return ""; } // 2 level: error
X wibble2() { return X(""); } // 1 level: ok
Even here you have same error:
void foobar(X x) {
}
int main()
{
foobar(X(""));// ok, 1 level
foobar ("f");
// error: could not convert '(const char*)"f"' from 'const char*' to 'X'
}

Resources