refactor - remove CRPT - c++11

I have custom List class like this:
template<class T>
struct iList{
constexpr bool empty() const{
return static_cast<const T *>(this)->size() == 0;
}
// several methods like empty(), some are non const.
};
// there are several classes like this one with different implementations
struct MyList : iList<MyList>{
constexpr unsigned size() const{
return 5;
}
};
int main(){
constexpr MyList list;
static_assert( ! list.empty() );
}
code is constexpr and simplified so I can use static_assert.
I want to get rid of CRTP pattern, because templates become way too ugly. However I do not want to use virtual functions.
One way I am thinking is following:
struct iList2{
protected:
template<class LIST>
constexpr static bool empty_(const LIST &list){
return list.size() == 0;
}
};
struct MyList2 : iList2{
constexpr unsigned size() const{
return 5;
}
constexpr bool empty() const{
return empty_(*this);
}
};
int main(){
constexpr MyList2 list2;
static_assert( ! list2.empty() );
}
In this case I need to call empty_ static member function in each list.
Another way is to use mixin, e.g. to inherit MyList and add empty() method. If I do this as templated class, I can even make typedef. However I do not like this approach as well.
Is there any possibility I am missing?

Related

using decltype w/ parameter pack for C++11

I'm trying to get the multi_index_t code from the second answer here answered by davidhigh to work with C++11. C++11 does not support auto& type returns.
I converted the return types for the class, but I don't understand how/if it's possible to support the helper function multi_index() without using C++14.
The code:
#include<array>
template<int dim>
struct multi_index_t
{
std::array<int, dim> size_array;
template<typename ... Args>
multi_index_t(Args&& ... args) : size_array(std::forward<Args>(args) ...) {}
struct iterator
{
struct sentinel_t {};
std::array<int, dim> index_array = {};
std::array<int, dim> const& size_array;
bool _end = false;
iterator(std::array<int, dim> const& size_array) : size_array(size_array) {}
iterator& operator++()
{
for (int i = 0;i < dim;++i)
{
if (index_array[i] < size_array[i] - 1)
{
++index_array[i];
for (int j = 0;j < i;++j) { index_array[j] = 0; }
return *this;
}
}
_end = true;
return *this;
}
std::array<int, dim>& operator*() { return index_array; }
bool operator!=(sentinel_t) const { return !_end; }
};
iterator begin() const { return iterator{ size_array }; }
iterator end() const { return typename iterator::sentinel_t{}; }
};
template<typename ... index_t>
auto multi_index(index_t&& ... index) // <-- this doesn't compile
{
static constexpr int size = sizeof ... (index_t);
auto ar = std::array<int, size>{std::forward<index_t>(index) ...};
return multi_index_t<size>(ar);
}
According to this answer, you can't recursively expand the variadic function template via decltype(). Any ideas?
C++11 does not support auto& type returns.
So you can simply explicit the types.
For multi_index() you have that return a multi_index_t<size>, where size is sizeof...(index_t), so you can write
template<typename ... index_t>
multi_index_t<sizeof...(index_t)> multi_index(index_t&& ... index)
According to this answer, you can't recursively expand the variadic function template via decltype.
Correct, but I don't see recursion in your multi_index() function, so I don't see how apply recursion over decltype().
If you really want (but why?), you can explicit the returning type through decltype() as follows
template<typename ... index_t>
auto multi_index(index_t&& ... index)
-> decltype( multi_index_t<sizeof...(index_t)>
{ std::array<int, sizeof...(index_t)>
{{ std::forward<index_t>(index) ... }} } )
but I don't see a reason to do this instead of simply explicit multi_index_t<sizeof...(index_t)>

Explicit member function specialisation

I am unable to specialize the template member function below. I have looked at the solution given to answer similar question on SOF but the solution that is proposed is same as the code I have below but it does not seem to work. I am missing something for sure.
enum EStep
{
eStep1, eStep2, eStep3
};
template<int16_t iDevice>
struct Device
{
template<EStep step>
static constexpr bool isType() { return false; }
};
template<> template<>
constexpr bool Device<int16_t>::isType<eStep1>()
{
return true;
}
template<> template<>
constexpr bool Device<int16_t>::isType<eStep1>()
{
return true;
}
Device is a template of int16_t, so to specialize it, you'd need to provide an int16_t value as the template argument. e.g.
template<> template<>
constexpr bool Device<999>::isType<eStep1>()

boost::iterator_facade operator->() fails to compile

Consider the following code:
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template < typename _Iterator, typename _Reference >
class Section
: public boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
>
{
private:
// Define the type of the base class:
typedef boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
> base_type;
public:
// The following type definitions are common public typedefs:
typedef Section< _Iterator, _Reference > this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef _Iterator iterator_type;
public:
explicit Section( const iterator_type it )
: m_it( it )
{ }
// Copy constructor required to construct a const_iterator from an iterator:
template < typename _U >
Section( const Section< _U, _Reference > it )
: m_it( it.m_it )
{ }
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template < typename _Iterator, typename _Reference > friend class Section;
void increment( ){ ++m_it; } // Advance by one position.
void decrement( ){ --m_it; } // Retreat by one position.
void advance( const difference_type& n ){ m_it += n }; // Advance by n positions.
bool equal( const this_type& rhs ) const{ return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference( ) const { return m_it->second; } // Access the value referred to.
difference_type distance_to( const this_type& rhs ) const{ return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current "section" iterator:
iterator_type m_it;
};
struct Data
{
void f( ) const
{ }
};
typedef std::map< int, Data > map_type;
typedef Section< const map_type::const_iterator, const Data& > iterator_type;
map_type g_map;
iterator_type begin( )
{
return iterator_type( g_map.begin( ) );
}
void main( )
{
iterator_type i = begin( );
// i->f( ); // <--- error C2039: 'f' : is not a member of 'std::_Tree_const_iterator<_Mytree>'
( *i ).f( );
}
So the iterator facade shall return a reference to Data type. This works well when dereference operator is called but compile fails when operator->() is called. So I am a bit confused because operator->() tries to return a std::map::iterator. Any ideas ?
The iterator returns an iterator on dereference. To get the f part, you need to dereference twice.
It looks a lot like you misunderstood the meaning of the template arguments to iterator_facade. The second argument is not supposed to be any iterator type (this is what causes all your trouble). Instead you should use it to name your value_type.¹
From the way you specified the dereference operation (and Ref) and wanted to use it in main (i->f()) it looks like you just wanted to iterate the map's values. So, I'd rewrite the whole thing using more descriptive names as well, and here it is, working:
Live On Coliru
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template <typename Map, typename Value = typename Map::mapped_type>
class MapValueIterator : public boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Value const&> {
private:
// Define the type of the base class:
typedef Value const& Ref;
typedef boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Ref> base_type;
public:
// The following type definitions are common public typedefs:
typedef MapValueIterator<Map> this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef typename Map::const_iterator iterator_type;
public:
explicit MapValueIterator(const iterator_type it) : m_it(it) {}
// Copy constructor required to construct a const_iterator from an iterator:
template <typename U, typename V> MapValueIterator(const MapValueIterator<U,V> it) : m_it(it.m_it) {}
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template <typename U, typename V> friend class MapValueIterator;
void increment() { std::advance(m_it); } // Advance by one position.
void decrement() { std::advance(m_it, -1); } // Retreat by one position.
void advance(const difference_type &n) { std::advance(m_it, n); } // Advance by n positions.
bool equal(const this_type &rhs) const { return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference() const { return m_it->second; } // Access the value referred to.
difference_type distance_to(const this_type &rhs) const { return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current iterator:
iterator_type m_it;
};
#include <iostream>
struct Data {
void f() const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
typedef std::map<int, Data> map_type;
template <typename Map>
MapValueIterator<Map> map_value_iterator(Map const& m) {
return MapValueIterator<Map>(m.begin());
}
int main() {
map_type g_map;
auto i = map_value_iterator(g_map);
i->f();
}
Which prints the output
void Data::f() const
as you'd expect.
Note that there are numerous places where I implemented the member functions using standard library facilities. Note as well, the iterator "mimics" random access, but it won't have the expected performance characteristics (increment is O(n)).
Final note: I'd recommend against having the implicit conversion constructor. I think you can do without it.
¹ The reference-type should typically be the same (but ref-qualified) except in rare cases where you actually "proxy" the values. This is an advanced topic and rarely should be used.

VS2015 internal compiler error when calling base class constexpr method

the following code produces an internal compiler error (VS2015)
struct A
{
constexpr A(){}
constexpr int bar()
{
return 3;
}
};
struct B : A
{
constexpr B(){}
constexpr int foo()
{
return A::bar();
}
};
int main()
{
constexpr B b;
constexpr int dummy = b.foo();
return 1;
}
However, if i'd remove the A:: qualifier:
constexpr int foo()
{
return bar();
}
it will be compiled.
problem arises when these methods have the same name, and I need to invoke the base class method. (e.g. when using recursive template inheritence)
any workarounds?
The actual problem is b is declared as const (constexpr implies const on objects) and you are trying to call non-const (since C++14, constexpr doesn't imply const on methods, see here) method with the const object...
According to the standard, you should not be able to solve the problem by simply removing A:: nor by the static_cast the way you did. Pre-RTM version of Visual Studio 2015 allows you to do this only because its support for constexpr is preliminary and very buggy. C++11 constexpr (but unfortunately not C++14 extended constexpr) expected to be fully supported in the RTM version of VS 2015 (see here).
The correct version of your code is:
struct A
{
constexpr A(){}
constexpr int bar() const
{
return 3;
}
};
struct B : A
{
constexpr B(){}
constexpr int foo() const
{
return A::bar();
}
};
int main()
{
constexpr B b;
constexpr int dummy = b.foo();
return 1;
}
Found a solution.
"this" should be casted to const A*:
struct B : A
{
constexpr B(){}
constexpr int foo()
{
return static_cast<const A*>(this)->bar();
}
};
Also works when the methods have the same name.

false behaviour of is_base_of when used together with bind

Using variadic template arguments together with a simple template argument I have experienced some strange behaviour of is_base_of when it was instantiated from a binded functor.
Here is the code:
template <class T, class Index>
class Base{};
template<typename T>
struct Checker {
typedef int result_type;
// Returns 1 if a given T type is descendant of Base<T,First>
template<typename First, typename ...Args>
result_type operator()(First&& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
template<typename ...Args>
result_type check(const std::true_type&, Args&&... params)
{
return 1;
}
template<typename ...Args>
result_type check(const std::false_type&, Args&&... params)
{
return 0;
}
};
struct A {};
struct B : Base<B,int> {};
int main()
{
Checker<A> ch1;
std::cout<<ch1(3.14)<<std::endl;
Checker<B> ch2;
std::cout<<ch2(1 ,3.14)<<std::endl; // output is 1
std::cout<<std::bind(ch2, 1, 3.14)()<<std::endl; // output is 0 but it should be 1 !
return 0;
}
The program output is:
0
1
0
But I would expect:
0
1
1
Am I using the variadic templates in a wrong way? Is there any other (correct) way to get the first type of a variadic type list like Args? Why this is a problem only when it is used with the bind expression?
Note, if I am modifing the Base template to have only one template parameter, then the bind expression works:
template <class T>
class Base{};
template<typename T>
struct Checker {
typedef int result_type;
// Returns 1 if a given T type is descendant of Base<T>
template<typename ...Args>
result_type operator()(Args&&... params)
{
return check(std::is_base_of<Base<T>, T>(),
std::forward<Args>(params)...);
}
template<typename ...Args>
result_type check(const std::true_type&, Args&&... params)
{
return 1;
}
template<typename ...Args>
result_type check(const std::false_type&, Args&&... params)
{
return 0;
}
};
struct A {};
struct B : Base<B> {};
int main()
{
Checker<A> ch1;
std::cout<<ch1(3.14)<<std::endl;
Checker<B> ch2;
std::cout<<ch2(3.14)<<std::endl; // output is 1
std::cout<<std::bind(ch2, 3.14)()<<std::endl; // output is 1 this time!
return 0;
}
You're not getting the expected output because the data-type of First in your Checker function object when called after std::bind() is of type int&, not int.
Therefore std::is_base_of<Base<B,int&>, B> does not instantiate to a std::true_type for the call to Checker::check.
The problem is that std::bind is creating an object that internally stores the arguments for the function you are passing to it. Therefore there is a named l-value as a non-static data-member of the object returned by std::bind that is holding the value you passed as an argument to be bound to your function. When that non-static data-member is then passed to the r-value reference at the time you call the operator() of the functor, it's passed as an l-value reference, since it is no longer a temporary object. You would have a similar problem if you did something like:
int x = 1;
Checker<B> ch2;
std::cout<<ch2(x, 3.14)<<std::endl;
The named-value x is an l-value, and would be passed to the first argument in your operator() method as an l-value reference, not as temporary, since first is a r-value reference. Therefore your type would end up again as an int& and not an int, and you'd print a value of 0.
To fix this problem, you can do something like:
template<typename First, typename ...Args>
result_type operator()(First&& first, Args&&... params)
{
if (std::is_reference<First>::value)
{
return check(std::is_base_of<Base<T, typename std::remove_reference<First>::type>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
else
{
return check(std::is_base_of<Base<T,First>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
}
This will strip off the reference-type of the object and give you the results you want.
Unfortunately std::is_reference did not give me the expected result on a more complicated issue.
So finally I choosed providing the reference and const-reference overloads:
template<typename First, typename ...Args>
result_type operator()(First& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
first,
std::forward<Args>(params)...);
}
template<typename First, typename ...Args>
result_type operator()(const First& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
first,
std::forward<Args>(params)...);
}

Resources