Issue with the templatized version of insertion sort - sorting

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.

Related

Resolve <unresolved overloaded function type> in std::async call

Can't resolve this instance of calling std::lower_bound from std::async. Example:
#include <vector>
#include <algorithm>
#include <future>
#include <iostream>
int main() {
std::vector<int> v = {1,3,4,6,7};
auto res = std::async(std::launch::async, std::lower_bound, v.begin(), v.end(), 4);
std::cout << *res.get() << std::endl;
return 0;
}
Compiler output makes it look like it doesn't realize std::launch::async is a launch policy and it should use the async call with the launch policy but I could be wrong.
test.cpp:8:84: error: no matching function for call to ‘async(std::launch, <unresolved overloaded function type>, std::vector<int>::iterator, std::vector<int>::iterator, int)’
res = std::async(std::launch::async, std::lower_bound, v.begin(), v.end(), 3);
^
In file included from test.cpp:3:0:
/usr/include/c++/6/future:1709:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^~~~~
/usr/include/c++/6/future:1709:5: note: template argument deduction/substitution failed:
test.cpp:8:84: note: couldn't deduce template parameter ‘_Fn’
res = std::async(std::launch::async, std::lower_bound, v.begin(), v.end(), 3);
^
In file included from test.cpp:3:0:
/usr/include/c++/6/future:1739:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...)
async(_Fn&& __fn, _Args&&... __args)
^~~~~
/usr/include/c++/6/future:1739:5: note: template argument deduction/substitution failed:
/usr/include/c++/6/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’:
test.cpp:8:84: required from here
/usr/include/c++/6/future:1739:5: error: no type named ‘type’ in ‘class std::result_of<std::launch()>’
std::lower_bound is a function template, you have to explicitly specify its arguments to be able to pass it around:
int main() {
using V = std::vector<int>;
V v = {1,3,4,6,7};
auto res = std::async(std::launch::async, std::lower_bound<V::iterator, int>, v.begin(), v.end(), 4);
std::cout << *res.get() << std::endl;
return 0;
}

How to prevent accidental emission of constexpr functions

Ben Deane mentions the throw trick, which ensures a link error when a constexpr function is used in a non-constexpr context.
Here is my take:
#include <iostream>
struct Exc;
constexpr int foo( int a )
{
if( a == 42 )
{
throw Exc{};
}
return 666;
}
int main()
{
constexpr auto ret = foo(43);
std::cout << ret << "\n";
return ret;
}
But I couldn't make it work (clang++ 3.8.1-23 and g++ 6.3.0):
$ clang++ -std=c++14 main.cpp
main.cpp:9:15: error: invalid use of incomplete type 'ExcBase'
throw ExcBase{};
^~~~~~~~~
main.cpp:3:8: note: forward declaration of 'ExcBase'
struct ExcBase;
^
1 error generated.
A comment in this thread suggests another trick:
#include <iostream>
constexpr int foo( int a )
{
if( a == 42 )
{
(void)reinterpret_cast<int>(a);
}
return 666;
}
int main()
{
constexpr auto ret = foo(43);
std::cout << ret << "\n";
return ret;
}
Which works: no errors or warnings; when the invocation is replaced with foo(42), clang returns:
$ clang++ -std=c++14 main.cpp
main.cpp:19:20: error: constexpr variable 'ret' must be initialized by a constant expression
constexpr auto ret = foo(42);
^ ~~~~~~~
main.cpp:10:15: note: reinterpret_cast is not allowed in a constant expression
(void)reinterpret_cast<int>(a);
^
main.cpp:19:26: note: in call to 'foo(42)'
constexpr auto ret = foo(42);
^
1 error generated.
Which is great. But gcc compiles the code happily in both cases. And now the question. How can a constexpr function be written in such a way, that it cannot be used in non-constexpr environments?
The problem is you actually instantiate (call constructor) a struct which is of incomplete type. This trick you talk about requires any symbol which will not be found at link time. So instead of struct you may use int:
http://coliru.stacked-crooked.com/a/3df5207827c8888c
#include <iostream>
extern int Exc;
constexpr int foo( int a )
{
if( a == 42 )
{
throw Exc;
}
return 666;
}
int main()
{
// Compiles
constexpr auto ret = foo(43);
std::cout << ret << "\n";
// This will show linker error as expected:
// /tmp/ccQfT6hd.o: In function `main':
// main.cpp:(.text.startup+0x4c): undefined reference to `Exc'
// collect2: error: ld returned 1 exit status
int nn;
std::cin >> nn;
auto ret2 = foo(nn);
return ret;
}

C++ range-for and boost::irange

I'm using boost::irange and created a helper function to simplify the code by removing the need for explicit template parameters. I don't understand why it doesn't work. Here's the code:
#include <iostream>
#include <boost/range/irange.hpp>
template<typename T>
boost::irange<T> range_from_zero(T limit)
{
return boost::irange<T>(T(), limit);
}
int main() {
size_t end = 100;
for (auto i : range_from_zero(0,end))
std::cout << i << ' ';
return 0;
}
There's a live version here https://ideone.com/VVvW6e, which produces compilation errors
prog.cpp:5:8: error: 'irange<T>' in namespace 'boost' does not name a type
boost::irange<T> range_from_zero(T limit)
^
prog.cpp: In function 'int main()':
prog.cpp:12:41: error: 'range_from_zero' was not declared in this scope
for (auto i : range_from_zero(0,end))
If I use boost::irange directly in the range-for, then it works:
#include <iostream>
#include <boost/range/irange.hpp>
int main() {
size_t end = 100;
for (auto i : boost::irange<size_t>(0,end))
std::cout << i << ' ';
return 0;
}
this works fine: https://ideone.com/TOWY6H
I thought maybe is was a problem using range-for on the return of a function, but it isn't; this works using a std::vector:
#include <iostream>
#include <boost/range/irange.hpp>
template<typename T>
std::vector<T> range_from_zero(T limit)
{
auto range = boost::irange<T>(T(), limit);
return { std::begin(range), std::end(range) };
}
int main() {
size_t end = 100;
for (auto i : range_from_zero(end))
std::cout << i << ' ';
return 0;
}
See https://ideone.com/TYRXnC
Any ideas, please?
But, first off, what's wrong with Live On Coliru
for (size_t i : irange(0, 100))
or even Live On Coliru
size_t end = 100;
for (auto i : irange(0ul, end))
irange is a function template, and it cannot be used as a return type.
The return type is integer_range or strided_integer_range. As such, irange is already the function you were looking for.
Only, you didn't pass arguments that could be unambiguously deduced. If you can to allow this, "copy" irange() implementation using separate template argument types for the boundary values and use e.g. std::common_type<T1,T2>::type as the range element.
Here's my stab at writing range_from_zero without naming implementation details in the interface:
Live On Coliru
#include <iostream>
#include <boost/range/irange.hpp>
template <typename T>
auto izrange(T upper) -> decltype(boost::irange(static_cast<T>(0), upper)) {
return boost::irange(static_cast<T>(0), upper);
}
int main() {
size_t end = 100;
for (size_t i : izrange(end))
std::cout << i << ' ';
}

std::initializer_list with Multiple Types

I'm having trouble with std::initializer_list. I reduced it down to a simple example:
#include <initializer_list>
#include <cstdio>
class Test {
public:
template <typename type> Test(const std::initializer_list<type>& args) {}
};
int main(int argc, char* argv[]) {
Test({1,2});
getchar();
return 0;
}
When compiled using g++ test_initializer.cpp -std=c++0x, it compiles and runs well. However, if line 11 is changed to Test({1,2.0});, one gets:
ian#<host>:~/Desktop$ g++ test_initializer.cpp -std=c++0x
test_initializer.cpp: In function ‘int main(int, char**)’:
test_initializer.cpp:11:14: error: no matching function for call to ‘Test::Test(<brace-enclosed initializer list>)’
test_initializer.cpp:11:14: note: candidates are:
test_initializer.cpp:7:28: note: template<class type> Test::Test(const std::initializer_list<_Tp>&)
test_initializer.cpp:5:7: note: constexpr Test::Test(const Test&)
test_initializer.cpp:5:7: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const Test&’
test_initializer.cpp:5:7: note: constexpr Test::Test(Test&&)
test_initializer.cpp:5:7: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘Test&&’
I suspect this happens because the compiler can't figure out what type to make the initializer list. Is there a way to fix the example so that it works with different types (and still uses initializer lists)?
An std::initializer_list takes only one type. If you need different types, you can use variadic templates:
template<typename... Args>
Test(Args&&... args);
/* ... */
int main()
{
Test(1, 2.0);
}
Would a std::tuple<int.double> work for the OP? If the code will always have a int followed by a double, then the OP could get strict type-checking for all arguments, which the variable arguments solution does not allow. The std::tuple<>, however, would not work for any number or order of values, so may not be appropriate for all use cases.
Let the initializer_list hold the most arbitrary pointers, void*, and do your own casting from there. Here is an example.
#include <initializer_list>
#include <iostream>
using std::initializer_list;
using std::cout;
using std::endl;
class Person {
private:
string _name;
int _age;
public:
Person(initializer_list<void*> init_list) {
auto it = init_list.begin();
_name = *((string*)(*it));
it++;
_age = *((int*)(*it));
}
void print() {
cout << "name: " << _name << ". age: " << _age << endl;
}
};
int main(void) {
string name{"Vanderbutenburg};
int age{23};
Person p{&name,&age};
p.print(); // "name: Vanderbutenburg. age: 23"
return 0;
}

How to convert boost::multiprecision::int512_t to boost::multiprecision::cpp_dec_float_100?

I'm using boost::multiprecision recently. My code like this:
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace bm = boost::multiprecision;
int main(void) {
bm::int512_t a = 12;
bm::cpp_dec_float_100 f = a;
std::cout << f * 3.14 << std::endl;
return 0;
}
It didn't compiled. Error shows:
b.cpp: In function ‘int main()’:
b.cpp:9:28: error: conversion from ‘boost::multiprecision::int512_t {aka boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<512u, 512u, (boost::multiprecision::cpp_integer_type)1u, (boost::multiprecision::cpp_int_check_type)0u, void> >}’ to non-scalar type ‘boost::multiprecision::cpp_dec_float_100 {aka boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> >}’ requested
bm::cpp_dec_float_100 f = a;
^
How can I convert it correctly? Thanks a lot!
I new to this stuff myself but I've been using boost multi_precision quite a lot,
I imagine the below should work
bm::cpp_dec_float_100 f = bm::cpp_dec_float_100 f(a);

Resources