How is std::is_integral implemented? - c++11

I am not familiar with Template magic in cpp. After reading what 'TemplateRex' said in this link, I was confused about how std::is_intergral works.
template< class T >
struct is_integral
{
static const bool value /* = true if T is integral, false otherwise */;
typedef std::integral_constant<bool, value> type;
};
I can understand how SFINAE works and how traits works. After refering cppreference, implementation of 'is_pointer" was found instead of 'is_integral' which looks like this :
template< class T > struct is_pointer_helper : std::false_type {};
template< class T > struct is_pointer_helper<T*> : std::true_type {};
template< class T > struct is_pointer : is_pointer_helper<typename std::remove_cv<T>::type> {};
Do 'is_integral' have similar implementation? How?

From here we have that:
Checks whether T is an integral type. Provides the member constant value which is equal to true, if T is the type bool, char, char16_t, char32_t, wchar_t, short, int, long, long long, or any implementation-defined extended integer types, including any signed, unsigned, and cv-qualified variants. Otherwise, value is equal to false.
Something like this is probably along the way you can implement it:
template<typename> struct is_integral_base: std::false_type {};
template<> struct is_integral_base<bool>: std::true_type {};
template<> struct is_integral_base<int>: std::true_type {};
template<> struct is_integral_base<short>: std::true_type {};
template<typename T> struct is_integral: is_integral_base<std::remove_cv_t<T>> {};
// ...
Note that std::false_type and std::true_type are specializations of std::integral_constant. See here for further details.

Related

Using iterator_traits to deduce value type from pair of iterators

I have a type
typedef std::pair<ConstIterator, ConstIterator> Range;
with
typedef typename std::vector<T>::const_iterator ConstIterator;
I would now like to use std::iterator_traits to deduce the type the iterators of a Range are pointing to.
Could anybody please tell me how I can achieve this, from an object of type Range?
You can write a type trait, partially specialized on a pair:
template <typename T>
struct value_type {
using type = typename std::iterator_traits<T>::value_type;
};
template <typename T>
struct value_type<std::pair<T, T>>
: value_type<T>
{ };
This will support both your pair based ranges, and most iterables:
template<class R>
struct value_type {
using iterator_type = decltype( std::begin(std::declval<R>()) );
using type=typename std::iterator_traits<iterator_type>::value_type;
};
template<class It>
struct value_type<std::pair<It,It>> {
using type=typename std::iterator_traits<It>::value_type;
};
template<class X>
using value_t = typename value_type<X>::type;
note that the value type of a const iterator is a non-const value.
The above is not SFINAE friendly -- an industrial quality one would be.
You're explicitly allowed to add template specializations to the std namespace for user-defined types (thanks Barry for the precision !). If you rework your Range to be an actual type (not just a typedef), you can do this :
struct Range : std::pair<ConstIterator, ConstIterator> {
using std::pair<ConstIterator, ConstIterator>::pair;
};
namespace std {
template <>
struct iterator_traits<Range> : iterator_traits<ConstIterator> {};
}
When you buff your Range a bit, I expect this to evolve into :
namespace std {
template <class T>
struct iterator_traits<Range<T>> : iterator_traits<T> {};
}

How to access template template parameters in type alias?

Is it possible to use template template arguments inside a type alias? For example is it possible to write a type alias similar to this:
#include "tuple"
template<
template<class... Types> class Container,
class... Types
> using another_tuple = std::tuple<Types...>;
another_tuple<std::tuple<int>> t;
which, when given e.g. std::tuple, uses its Types for something else? Both GCC and Clang mention class templates in their errors, how do I avoid needing a class template? If I remove all ...s GCC error changes to:
error: wrong number of template arguments (1, should be 2)
another_tuple<std::tuple<int>> t;
^
which I don't understand. Container itself doesn't have to be a template but I couldn't figure out how to use std::tuple in its place.
Update based on n.m.s answer, the correct format is:
another_tuple<std::tuple, int> t;
and similarly even when the types are in a container:
using types = std::tuple<int, char>;
another_tuple<std::tuple, types> t;
which has a bit of redundant code but should be good enough.
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<class...>struct types{using type=types;};
template<template<class...>class Z, class types>
struct apply_types;
template<template<class...>class Z, class types>
using apply_types_t=type_t<apply_types<Z,types>>;
template<template<class...>class Z, class...Ts>
struct apply_types<Z,types<Ts...>>:tag<Z<Ts...>> {};
template<template<class...>class M, class types>
struct map;
template<template<class...>class M, class types>
using map_t=type_t<map<M,types>>;
template<template<class...>class M, class...Ts>
struct map<M,types<Ts...>>:types<M<Ts>...>{};
template<class...lists>
struct concat:types<>{};
template<class...lists>
using concat_t=type_t<concat<lists...>>;
template<class...lhs, class...rhs>
struct concat<types<lhs...>,types<rhs...>>:
types<lhs...,rhs...>
{};
template<class types>
struct concat<types>:
types
{};
template<class types, class...more_types>
struct concat<types, more_types...>:
concat<types, concat_t<more_types...>>
{};
template<class A, template<class...>class C, class T, class F>
struct condition:std::conditional<C<A>{}, T, F>{};
template<template<class...>class Z, class... T>
struct bind_1st_n {
template<class...Ts>
using apply=Z<T..., Ts...>;
};
template<class Tok, class list, class A>
struct replace_helper:
condition<A, bind_1st_n<std::is_same, Tok>::template apply, list, types<A>>
{};
template<class list, class if_this, class then_these>
struct replace:
concat<
map_t<
bind_1st_n<replace_helper,if_this, then_these>::template apply,
list
>
>
{};
struct placeholder {};
template<class T> struct get_args;
template<class T> using get_args_t=type_t<get_args<T>>;
template<template<class...>class Z, class...Ts>
struct get_args<Z<Ts...>>:types<Ts...> {};
template<template<class...>class Z, class types>
struct apply;
template<template<class...>class Z, class types>
using apply_t=type_t<apply<Z,types>>;
template< class Container >
using another_tuple = apply_t< std::tuple, get_args_t<Container> >;
and if you want the list to expand with int in front, and double at the end:
template< class Container >
using another_tuple = apply_t< std::tuple,
replace_t<
types<int, placeholder, double>,
placeholder,
get_args_t<Container>
>
>;
which builds the list to apply, then applies it in two steps.
None of this code has been compiled.

SFINAE to set alias template

I was wondering if it is possible to use SFINAE to set an alias template in a different class depending on the existence or not of an alias in a traits class.
template<class T>
struct Foo_Traits;
struct Foo1;
template<>
struct Foo_Traits<Foo1>
{
using type1 = Bar1;
using type2 = Bar2;
};
struct Foo2;
template<>
struct Foo_Traits <Foo2>
{
using type1 = Bar3;
};
Essentially we have 2 classes Foo1 and Foo2 and their traits class that define type aliases in this case to simplify it.
In all cases we will have type1 alias and in some cases we will have a type2.
In a different class (in my cases it is actually the base class of Foo) I want to set aliases for these types.
template<typename ImplT>
class FooBase
{
using T1 = typename Foo_Traits<ImplT>::type1;
using T2 = typename std::conditional< defined<typename Foo_Traits<ImplT>::type1>::value ,
typename Foo_Traits<ImplT>::type2,
T1>::type;
};
How can I actually achieve something of the sort that is written in pseudocode over at
using T2 = etc...
Your answer can be found in N3911 that proposes void_t.
Given:
template <typename...>
using void_t = void;
You can write your has_type2_member predicate like so:
template <typename, typename = void>
struct has_type2_member : std::false_type {};
template <typename T>
struct has_type2_member<T, void_t<typename T::type2>> : std::true_type {};
We can't use this predicate directly, but we can modify it to our needs.
template <typename ImplT>
class FooBase
{
using T1 = typename Foo_Traits<ImplT>::type1;
template <typename, typename = void>
struct type2_or_type1 {
using type = T1;
};
template <typename T>
struct type2_or_type1<T, void_t<typename T::type2>> {
using type = typename T::type2;
};
using T2 = typename type2_or_type1<Foo_Traits<ImplT>>::type;
};

Is there a way to print a constexpr string during compiletime?

I'm trying to do the following (only relevant parts of code below):
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
static constexpr char* err_value = "Type is not a container model";
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
static_assert(false, IsContainerCheck<ResultType>::err_value)
return 0;
}
};
template<>
struct run<true_t> {
constexpr static int apply() {
return 0;
}
};
}
This fails because the static_assert allows only literals to be printed. The same is with BOOST_STATIC_ASSERT_MSG macro.
So my question is - is there any way to output a constexpr string during compilation?
If there is a gcc extension providing this functionality that would also be great.
Used compiler gcc 4.8.1
GCC does not provide such a mechanism as you want. However you will not need
it if you are able to refactor your code somewhat as illustrated in the
following program. (I have filled in a few gaps so as to give us a
compilable example):
#include <type_traits>
#include <vector>
template<typename ContainerType>
struct is_container
{
static bool const value = false;
};
template<>
struct is_container<std::vector<int>>
{
static bool const value = true;
};
template<typename ContainerType>
struct IsContainerCheck // : is_container<ContainerType> <- Uneccessary
{
static_assert(is_container<ContainerType>::value,
"Type is not a container model");
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
return (IsContainerCheck<ResultType>(),0);
}
};
// No such specialization is necessary. Delete it.
// template<>
// struct run<true_t> {
// constexpr static int apply() {
// return 0;
// }
//};
}
using namespace _check_concept;
int main(int argc, char **argv)
{
auto verdict0 = run<std::vector<int>>::apply();
(void)verdict0;
// The following line will static_assert: "Type is not a container model"
auto verdict1 = run<float>::apply();
(void)verdict1;
return 0;
}
In your specialization _check_concept::struct run<true_t> I presume that
true_t is not an alias or equivalent of std::true_type, but rather
just a place-holder for some ResultType that is a container type. As
the test program shows, no such specialization is now necessary, because
IsContainerCheck<ResultType>() will static_assert, or not, depending
on ResultType, in the unspecialized run<ResultType>::apply().
I had some time (and a good liqueur to come along with it) to think more about the problem. This is what I came up with:
namespace _details {
struct PassedCheck {
constexpr static int printError () {
return 0; //no error concept check passed
}
};
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept_impl;
template<template<typename> class ConceptCheck, typename FirstType, typename ...ModelTypes>
struct check_concept_impl<ConceptCheck, FirstType, ModelTypes...> : mpl::eval_if< typename ConceptCheck<FirstType>::type,
check_concept_impl<ConceptCheck, ModelTypes...>,
mpl::identity<ConceptCheck<FirstType>>>
{ };
template<template<typename> class ConceptCheck, typename LastType>
struct check_concept_impl<ConceptCheck, LastType> : mpl::eval_if<typename ConceptCheck<LastType>::type,
mpl::identity<PassedCheck>,
mpl::identity<ConceptCheck<LastType>>>
{ };
}
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept {
private:
typedef typename _details::check_concept_impl<ConceptCheck, ModelTypes...>::type result_type;
public:
// the constexpr method assert produces shorter, fixed depth (2) error messages than a nesting assert in the trait solution
// the error message is not trahsed with the stack of variadic template recursion
constexpr static int apply() {
return result_type::printError();
}
};
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
template<typename BoolType = false_t>
constexpr static int printError () {
static_assert(BoolType::value, "Type is not a container model");
return 0;
}
};
and the usage:
check_concept<IsContainerCheck, std::vector<int>, std::vector<int>, float, int>::apply();
The solution is probably not the most elegant one but I it keeps the assert message short:
In file included from ../main.cpp:4:0:
../constraint.check.hpp: In instantiation of ‘static constexpr int IsContainerCheck::printError() [with BoolType = std::integral_constant; ContainerType = float]’:
../constraint.check.hpp:61:34: required from ‘static constexpr int check_concept::apply() [with ConceptCheck = IsContainerCheck; ModelTypes = {std::vector >, std::vector >, float, int}]’
../main.cpp:25:83: required from here
../constraint.check.hpp:74:3: error: static assertion failed: Type is not a container model
static_assert(BoolType::value, "Type is not a container model");
The assert is issued in a constexpr method after the check_concept template specialization has been done. Embedding the static assert directly into the template class definition would drag the whole check_concept_impl recursion stack into the error message.
So changing the IsContainerCheck trait to something like (rest of the changes omitted for readibility):
template<typename ContainerType>
struct IsContainerCheck
{
static_assert(is_container<ContainerType>::type::value, "Type is not a container model");
};
would yield an error
../constraint.check.hpp: In instantiation of ‘struct IsContainerCheck’:
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, float, int>’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl >, float, int>, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, std::vector >, float, int>’
../constraint.check.hpp:53:84: required from ‘struct check_concept >, std::vector >, float, int>’
../main.cpp:25:81: required from here
../constraint.check.hpp:72:2: error: static assertion failed: Type is not a container model
static_assert(is_container::type::value, "Type is not a container model");
As you can see each recursive eval_if call is emended in the error description which is bad because it makes the error message dependent from the amount and type of template parameters.

Variadic typedefs, or "Bimaps done the C++0x way"

Short question: Can I typedef a variadic argument pack? I need template <typename ...T> struct Forward { typedef T... args; };.
Long version:
I was thinking about reimplementing the excellent boost bimap in C++0x. Recall that a bimap of two types S and T is a std::set of relations between S x and T y. The objects themselves are stored in two independent internal containers, and the relations track the associated iterators I suppose; both types can serve as keys via "left" and "right" lookup. Depending on the choice of internal containers, values may be unique or not, e.g. if the left container is a set and the right container is a multiset, then one x can map to many different ys, and right lookup gives an equal-range. Popular internal containers are set, multiset, vector and list, and maybe the unordered_* versions too.
So we need a type which accepts two containers as template parameters:
class Bimap<S, T, std::set, std::multiset>
But we must accept that the containers can take arbitrary many arguments, so we need to pass all those, too. If we just needed one set of variadic arguments, it wouldn't be a problem, since we could pass those directly. But now we need two sets of arguments, so I want to write a forwarder, to be used like so:
Bimap<int, int, std::set, std::set, Forward<std::less<int>, MyAllocator>, Forward<std::greater<int>, YourAllocator>> x;
Here's the template I came up with:
#include <set>
#include <cstdint>
template <typename ...Args>
struct Forward
{
typedef Args... args; // Problem here!!
static const std::size_t size = sizeof...(Args);
};
template <typename S, typename T,
template <typename ...SArgs> class SCont,
template <typename ...TArgs> class TCont,
typename SForward = Forward<>, typename TForward = Forward<>>
class Bimap
{
typedef SCont<S, typename SForward::args> left_type;
typedef TCont<T, typename TForward::args> right_type;
template <typename LeftIt, typename RightIt> struct Relation; // to be implemented
typedef Relation<typename left_type::const_iterator, typename right_type::const_iterator> relation_type;
};
int main()
{
Bimap<int, int, std::set, std::set, Forward<std::less<int>>, Forward<std::greater<int>>> x;
}
Unfortunately, in the indicated line in Forward I cannot figure out how to typedef the parameter pack! (The commented line gives a compiler error.)
[I suppose I could go for a lazy version Bimap<std::set<int, MyPred>, std::multiset<char, YourPred>> x; and extract the types via LeftCont::value_type and RightCont::value_type, but I thought it'd be nicer if I could make the key types my primary template arguments and allow defaulting to std::set containers.]
You can achieve what you want by encapsulating the variadic argument pack in a tuple and later using the following two helper template structs to forward the actual variadic arguments:
template<typename PackR, typename PackL>
struct cat;
template<typename ...R, typename ...L>
struct cat<std::tuple<R...>, std::tuple<L...>>
{
typedef std::tuple<R..., L...> type;
};
and
template<typename Pack, template<typename ...T> class Receiver>
struct Unpack;
template<typename ...Args, template<typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
typedef Receiver<Args...> type;
};
your code sample would look like this:
#include <set>
#include <cstdint>
#include <tuple>
template<typename PackR, typename PackL>
struct Cat;
template<typename ...R, typename ...L>
struct Cat<std::tuple<R...>, std::tuple<L...>>
{
typedef std::tuple<R..., L...> type;
};
template<typename Pack, template<typename ...T> class Receiver>
struct Unpack;
template<typename ...Args, template<typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
typedef Receiver<Args...> type;
};
template<typename ...Args>
struct Forward
{
//typedef Args... args; // Problem here!!
typedef std::tuple<Args...> args; // Workaround
static const std::size_t size = sizeof...(Args);
};
template<typename S, typename T,
template<typename ...SArgs> class SCont,
template<typename ...TArgs> class TCont,
typename SForward = Forward<> ,
typename TForward = Forward<>>
class Bimap
{
//typedef SCont<S, typename SForward::args> left_type;
//typedef TCont<T, typename TForward::args> right_type;
typedef typename Unpack<typename Cat<std::tuple<S>, typename SForward::args>::type, SCont>::type left_type; //Workaround
typedef typename Unpack<typename Cat<std::tuple<T>, typename TForward::args>::type, TCont>::type right_type; //Workaround
template<typename LeftIt, typename RightIt> struct Relation; // to be implemented
typedef Relation<typename left_type::const_iterator, typename right_type::const_iterator> relation_type;
};
int main()
{
Bimap<int, int, std::set, std::set, Forward<std::less<int>> , Forward<std::greater<int>>> x;
}
which compiles just fine under gcc 4.6.0
You can typedef a tuple. However, I wouldn't know how to then get the types back out again.
The easiest thing to do would be to just accept two full types.

Resources