boost::enable_if MSVC - c++

I have code, that compiles and runs as expected in gcc and doesn't compile in MSVC 2012 RC, i can't explain why, so it's bug in MSVC, or my code is incorrect?
#include <boost/mpl/vector.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/size.hpp>
#include <boost/utility/enable_if.hpp>
#include <vector>
#include <iostream>
namespace mpl = boost::mpl;
template<typename T,
typename = void>
struct Some
{
typedef std::vector<T> type;
};
template<typename T>
struct Some<T, typename boost::enable_if_c<mpl::is_sequence<T>::type::value>::type> :
public Some<typename mpl::front<T>::type>::type
{
};
int main()
{
typedef mpl::vector<int, double> vect_t;
typedef Some<vect_t> vector;
vector vect;
vect.push_back(1);
std::cout << "int: " << vect.at(0) << std::endl;
}
http://liveworkspace.org/code/45d78872a2c7f30192277a81c655b471
MSVC says, that push_back and at are not members of Some<vect_t>.
EDIT.
It looks like bug in MSVC 2012 since
#include <boost/mpl/vector.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/size.hpp>
#include <boost/utility/enable_if.hpp>
#include <vector>
#include <iostream>
namespace mpl = boost::mpl;
template<typename T, typename = void>
struct Some
{
typedef std::vector<T> type;
};
template<typename T>
struct Some<T, typename boost::enable_if_c<mpl::is_sequence<T>::type::value>::type> :
public std::vector<int>
{
};
int main()
{
typedef mpl::vector<int, double> vect_t;
typedef Some<vect_t>::type vector;
vector vect;
vect.push_back(1);
std::cout << "int: " << vect.at(0) << std::endl;
}
gives errors, that i can't push_back int into std::vector<boost::mpl::vector<int, double> >, so it choose general-case, not specialization...
EDIT.
Strange... But this works as expected
template<typename T>
struct Some<T, typename std::enable_if<boost::mpl::is_sequence<T>::value>::type> :
public std::vector<int>
{
};
So, i can't explain why, but MSVC 2012 cannot works with nested expressions in enable_if (or possibly in template parameters).
template<typename T>
struct is_int : public std::integral_constant<bool, false>
{
};
template<>
struct is_int<int> : public std::integral_constant<bool , true>
{
};
template<typename T, typename = void>
struct Some
{
typedef void type;
};
template<typename T>
struct Some<T, typename std::enable_if<is_int<T>::type::value>::type>
{
static_assert(is_int<int>::type::value, "asserted");
typedef T type;
};
int main()
{
static_assert(is_int<T>::type::value, "ass");
Some<int>::type t = 0;
}

I compile and run your code in MSVC 2010 successfully, so probably this is a bug in RC version of MSVC 2012. so event try it in MSVC 2012 final or wait for MSVC 2012 Express.

Related

Structs, templates use, and inheritance questions

I recently came across a script(below) in which I do not understand why we need to have structs in this script and why they have to inherit false/true types. I also do not understand why "template" is repeated.
#include <iostream>
#include <vector>
using namespace std;
template<typename T>
struct is_vector: false_type {}; //<- why does the struct have to inherit something and what does it do?
template<typename T, typename Alloc>
struct is_vector<vector<T, Alloc>> : true_type {};
template<class T>
void func(const vector<T> & vec){
for(const auto & x : vec)
if constexpr (is_vector<T>::value)
func(x);
else
cout << x << ' ';
}
int main(){
func(vector<int>{5,10,15});
func(vector<vector<int>>{{5,10,15},{20,25,30}});
}

Get boost::variant's type index with boost::mpl

boost::variant has member types which is some kind of boost::mpl structure.
Is there a way to get an index of type in that structure at compile time, so late in in runtime i could do
if(myVariantInstance.which() == typeIndex)
{
/*...*/
}
Instead of
if(myVariantInstance.type() == typeid(ConcreteType))
{
/*...*/
}
I found solution for getting index of type in boost::variant without boost::mpl if you are interested in.
#include <iostream>
#include <type_traits>
#include <boost/variant/variant.hpp>
using myvariant = boost::variant<int, bool, double, int>;
template <typename T, typename ... Ts>
struct type_index;
template <typename T, typename ... Ts>
struct type_index<T, T, Ts ...>
: std::integral_constant<std::size_t, 0>
{};
template <typename T, typename U, typename ... Ts>
struct type_index<T, U, Ts ...>
: std::integral_constant<std::size_t, 1 + type_index<T, Ts...>::value>
{};
template <typename T, typename ... Ts>
struct variant_first_same_type_idx;
template <typename T, typename Head, typename ... Tail>
struct variant_first_same_type_idx<T, boost::variant<Head, Tail ... >>
: type_index<T, Head, Tail ...>
{};
int main()
{
std::cout << variant_first_same_type_idx<int, myvariant>::value << std::endl;
std::cout << variant_first_same_type_idx<bool, myvariant>::value << std::endl;
std::cout << variant_first_same_type_idx<double, myvariant>::value << std::endl;
}
The output of this program is:
0
1
2
It's a bit convoluted, and there might be a better way, but you could use boost::mpl::copy. Here's something that ought to work, based off of the example from your comment:
#include <boost/variant.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/vector.hpp>
typedef boost::mpl::vector<int, long, char> MyMplVector;
typedef boost::mpl::find<MyMplVector, long>::type MyMplVectorIter;
static_assert(MyMplVectorIter::pos::value == 1, "Error");
typedef boost::variant<int, long, char> MyVariant;
typedef boost::mpl::vector<> EmptyVector;
typedef boost::mpl::copy<
MyVariant::types,
boost::mpl::back_inserter<EmptyVector>>::type ConcatType;
typedef boost::mpl::find<ConcatType, long>::type MyVariantTypesIter;
static_assert(MyVariantTypesIter::pos::value == 1, "Error");
#include <boost/mpl/index_of.hpp>
#include <iostream>
typedef boost::variant<int, std::string> VARIANT;
std::ostream &operator<<(std::ostream &_rS, const VARIANT&_r)
{ switch (_r.which())
{ default:
return _rS << "what the *";
case boost::mpl::index_of<VARIANT::types, int>::type::value:
return _rS << boost::get<int>(_r);
case boost::mpl::index_of<VARIANT::types, std::string>::type::value:
return _rS << boost::get<std::string>(_r);
}
}
PS. I was always curious about people using the visitor access pattern...
PPS. I know that one does not need to implement an output operator as boost::variant already provides one -- just for explanation purposes...

c++ template: boost::mpl::transform with template template parameter

Now that my previous question has a solution, more questions arise.
I want to use the wrap_into_container meta-function with boost::mpl::transform, e.g.:
#include <vector>
#include <list>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/mpl/transform.hpp>
namespace container
{
template <typename T> struct vector { typedef std::vector<T> type; };
template <typename T> struct list { typedef std::list<T> type; };
}
template<typename T, template <typename> class Container>
struct wrap_into_container
{
typedef typename Container<T>::type type;
};
int main()
{
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
typedef fusion::vector<int, float, int> vec_type;
typedef mpl::transform< vec_type, wrap_into_container<mpl::_1, container::vector> >::type wrapped_vec_type;
wrapped_vec_type w;
return w.size();
}
Link to coliru
But it seems like I cannot pass a template template parameter into mpl::transform ...
How can I solve this? Please provide a C++03 solution, since I cannot use C++11.
In boost::mpl, higher order functions are written by passing a fixed type with an internal apply template member (known as a metafunction class), rather than through the use of template-template parameters. Live Example.
#include <vector>
#include <list>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/mpl/transform.hpp>
#include <iostream>
namespace container
{
struct vector {
template<typename T> struct apply {
typedef std::vector<T> type;
};
};
struct list {
template <typename T> struct apply {
typedef std::list<T> type;
};
};
}
template<typename T, typename ContainerMaker>
struct wrap_into_container
{
typedef typename ContainerMaker::template apply<T>::type type;
};
int main()
{
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
typedef fusion::vector<int, float, int> vec_type;
typedef mpl::transform<
vec_type,
wrap_into_container<mpl::_1, container::vector>
>::type wrapped_vec_type;
wrapped_vec_type w;
std::cout << size(w) << "\n";
return size(w);
}
I don't know boost::mpl, so I can only speculate from what I've seen in the documentation.
I think what you need is
template<template <typename> class Container>
struct wrap_into_container
{
template<typename T>
struct map
{
typedef typename Container<T>::type type;
};
};
Followed by
typedef wrap_into_container<container::vector>::template map<mpl::_1> fun;
typedef transform<vec_type, fun>::type wrapped_vec_type;
In this case, fun is a class of the form C<mpl::_1> where C is a class template, and whose ::type is std::vector<mpl::_1>. I think this is what mpl::transform expects for its type map.
My only test is with my own version of transform, which works with template template arguments instead of placeholders for the type map. Check live example, where transform is defined using C++11 but the remaining part is C++03. In this example, I am only using
wrap_into_container<container::vector>::template map
as a template template argument to my transform, without the placeholder <mpl::_1>.
I hope this helps.

Get twice as wide type

basically, i'd like to (at compile time) get the twice-as-wide type from a stdint type. I can do it by hand like this
template <typename T>
class twice_as_wide{};
template<>
class twice_as_wide<uint8_t>
{
public:
typedef uint16_t type;
};
template<>
class twice_as_wide<int8_t>
{
public:
typedef int16_t type;
};
template<>
class twice_as_wide<uint16_t>
{
public:
typedef uint32_t type;
};
ect, I just want to make sure that this doesn't exist yet. I'm using visual studio 2010 C++0X (annoying, i know) and already have a boost dependency. Does anyone know of an existing implementation of this?
If you don't mind another boost dependency, then you could do this:
#include <type_traits>
#include <boost/integer.hpp>
template <typename T, bool is_unsigned = std::is_unsigned<T>::value>
struct twice_as_wide
{
typedef typename boost::uint_t< 2 * std::numeric_limits<T>::digits>::exact type;
};
template<typename T>
struct twice_as_wide<T, false>
{
typedef typename boost::int_t< 2 * (std::numeric_limits<T>::digits + 1)>::exact type;
};
template< typename T>
using twice_as_wide_t = typename twice_as_wide<T>::type;
I'd say, use Boost Integer. Demo that keeps signed-ness of the source type: Live on Coliru
#include <boost/integer.hpp>
#include <limits>
namespace helpers
{
// wrappers around Boost Integer http://www.boost.org/doc/libs/1_54_0/libs/integer/doc/html/boost_integer/integer.html#boost_integer.integer.sized
template <bool is_signed, int bin_digits> struct select_twice;
template <int bin_digits> struct select_twice<true, bin_digits> {
using type = typename boost::int_t<bin_digits + 1>::least;
};
template <int bin_digits> struct select_twice<false, bin_digits> {
using type = typename boost::uint_t<bin_digits>::least;
};
}
template <typename Int>
using select_twice = helpers::select_twice<std::numeric_limits<Int>::is_signed, std::numeric_limits<Int>::digits*2>;
template <typename Int>
using twice_t = typename select_twice<Int>::type;
int main()
{
static_assert(std::is_same<uint16_t, twice_t<uint8_t>>::value, "oops");
static_assert(std::is_same<uint32_t, twice_t<uint16_t>>::value, "oops");
static_assert(std::is_same<uint64_t, twice_t<uint32_t>>::value, "oops");
}

type mapping by templates

I'm looking for a way to map types, f.i. having a class Double:
class Double
{
public:
typedef double basic_type;
...
};
I'd like to be able to have a type caster so that
typeid(TypeToObjectType<double>::type) == typeid(Double)
Any ideas how to accomplish this (through partial specializations etc.) ?
You can achieve this through specialization :
template<class T>
struct TypeToObjectType;
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
Note that you have to provide a specialization for each of the types on which you want TypeToObjectType to work. Macros can be helpful here :
#define SPECIALIZE_TYPETOOBJECTTYPE(ObjectType) \
template<> struct TypeToObjectType<ObjectType::basic_type> { \
typedef ObjectType type; \
};
SPECIALIZE_TYPETOOBJECTTYPE(Int)
SPECIALIZE_TYPETOOBJECTTYPE(Double)
Sounds like you are looking for something like this:
template<typename T>
struct TypeToObjectType;
// specialization for T=double
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
Here TypeToObjectType<double>::type is Double and you can add other specializations for additional mappings.
This should work very well, however, I haven't tested this method for classes of mine. I have used an idea from the book "C++ Templates: The Complete Guide", paragraph 20.4.2
#include <iostream>
#include <string>
#include <list>
#include <type_traits>
template<typename... Ts>
struct type_mapper;
template<>
struct type_mapper<>
{
static void mapTo(...);
};
template<typename T, typename... Ts>
struct type_mapper<T, Ts...> : type_mapper<Ts...>
{
static typename T::second_type mapTo(typename T::first_type);
using type_mapper<Ts...>::mapTo;
};
template<typename T, typename MapperT>
struct GetTypeOnMap
{
using type = decltype(MapperT::mapTo(std::declval<T>()));
};
template<typename T, typename MapperT>
using get_type_on_mapping = typename GetTypeOnMap<T, MapperT>::type;
int main(void)
{
using mapper = type_mapper <
std::pair<int, double>,
std::pair<double, int>,
std::pair<float, std::string>>;
using shouldBeDouble = get_type_on_mapping<int, mapper>;
using shouldBeString = get_type_on_mapping<float, mapper>;
std::cout << shouldBeDouble{2.9};
std::cout << shouldBeString{"Hello"};
return 0;
}
EDIT:
Another one solution. More concise and flexible:
#include <complex>
#include <type_traits>
#include <cstdint>
#include <iostream>
#include <string>
template <typename V1, typename V2, typename T>
struct OnTypesEqual : std::bool_constant<std::is_same_v<V1, V2>> {
using type = T;
};
template <typename T>
struct default_type : std::true_type {
using type = T;
};
template<typename T>
using TypesMapper = typename std::disjunction<
OnTypesEqual<T, double, std::int8_t>,
OnTypesEqual<T, float, std::int16_t>,
OnTypesEqual<T, std::string, std::int32_t>,
OnTypesEqual<T, char, std::int64_t>,
default_type<void>
>::type;
int main()
{
std::cout << typeid(TypesMapper<double>).name() << std::endl;
std::cout << typeid(TypesMapper<float>).name() << std::endl;
std::cout << typeid(TypesMapper<std::string>).name() << std::endl;
std::cout << typeid(TypesMapper<char>).name() << std::endl;
return 0;
}