Is it possible to have a struct which may or may not have a member? Something like this:
template <typename T, typename A = some_type_with_size_0>
struct s {
T t;
A aux;
};
To be specific, if I asked for s<int, int> I would get a struct with two ints, but if I asked for s<int> I would get a struct with only an int.
In C++20, it will be possible to do what you're trying to do directly:
template <typename T, typename A = some_type_with_size_0>
struct s {
T t;
[[no_unique_address]] A aux;
};
See https://en.cppreference.com/w/cpp/language/attributes/no_unique_address.
In C++17, there's no straightforward way to specify a member that conditionally disappears. You need to write a full-blown partial specialization, like so:
template <typename T, typename A = void>
struct s {
T t;
A aux;
};
template <typename T>
struct s<T, void> {
T t;
};
This unfortunately requires you to repeat yourself in typing out all the common members (in this case only t). To avoid this, we can stick the conditionally present members in a base class:
template <typename T, typename A = void>
struct s : optional_aux<A> {
T t;
};
template <typename A>
struct optional_aux {
A aux;
};
template <>
struct optional_aux<void> { };
In the case where A = void, this base class is empty, so the compiler has discretion to remove it entirely, making sizeof(s<T, void>) potentially equal to sizeof(T). The [[no_unique_address]] attribute basically makes empty base class optimization available for members as well.
You can use a variadic template:
template <typename...> struct Generic;
template <typename T1> struct Generic<T1> {
T1 field1;
};
template <typename T1, typename T2> struct Generic<T1, T2> {
T1 field1;
T2 field2;
};
Related
Something is not working quite well for me. Is this the way to declare a class, that accepts only floating point template parameter?
template <typename T, swift::enable_if<std::is_floating_point<T>::value> = nullptr>
class my_float;
I fail to define methods outside this class. Doesn't compile, not sure why
Well... not exactly SFINAE... but maybe, using template specialization? Something as follows ?
template <typename T, bool = std::is_floating_point<T>::value>
class my_float;
template <typename T>
class my_float<T, true>
{
// ...
};
If you really want use SFINAE, you can write
template <typename T,
typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
class my_float
{
// ...
};
or also (observe the pointer there isn't in your example)
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
class my_float // ------------------------------------------------^
{
};
-- EDIT --
As suggested by Yakk (thanks!), you can mix SFINAE and template specialization to develop different version of your class for different groups of types.
By example, the following my_class
template <typename T, typename = void>
class my_class;
template <typename T>
class my_class<T,
typename std::enable_if<std::is_floating_point<T>::value>::type>
{
// ...
};
template <typename T>
class my_class<T,
typename std::enable_if<std::is_integral<T>::value>::type>
{
// ...
};
is developed for in two versions (two different partial specializations), the first one for floating point types, the second one for integral types. And can be easily extended.
You can also use static_assert to poison invalid types.
template <typename T>
class my_float {
static_assert(std::is_floating_point<T>::value,
"T is not a floating point type");
// . . .
};
It's a little bit more direct, in my opinion.
With either of the other approaches, e.g.
template <typename T, bool = std::is_floating_point<T>::value>
class my_float;
template <typename T> class my_float<T, true> { /* . . . */ };
my_float<int,true> is a valid type. I'm not saying that that's a bad approach, but if you want to avoid this, you'll have to encapsulate
my_float<typename,bool> within another template, to avoid exposing the bool template parameter.
indeed, something like this worked for me (thanks to SU3's answer).
template<typename T, bool B = false>
struct enable_if {};
template<typename T>
struct enable_if<T, true> {
static const bool value = true;
};
template<typename T, bool b = enable_if<T,is_allowed<T>::value>::value >
class Timer{ void start(); };
template<typename T, bool b>
void Timer<T,b>::start()
{ \* *** \*}
I am posting this answer because I did not want to use partial specialization, but only define the behavior of the class outside.
a complete workable example:
typedef std::integral_constant<bool, true> true_type;
typedef std::integral_constant<bool, false> false_type;
struct Time_unit {
};
struct time_unit_seconds : public Time_unit {
using type = std::chrono::seconds;
};
struct time_unit_micro : public Time_unit {
using type = std::chrono::microseconds;
};
template<typename T, bool B = false>
struct enable_if {
};
template<typename T>
struct enable_if<T, true> {
const static bool value = true;
};
template<typename T,
bool b = enable_if<T,
std::is_base_of<Time_unit,
T>::value
>::value>
struct Timer {
int start();
};
template<typename T, bool b>
int Timer<T, b>::start() { return 1; }
int main() {
Timer<time_unit_seconds> t;
Timer<time_unit_micro> t2;
// Timer<double> t3; does not work !
return 0;
}
Is it possible to write a metafunction that, given a type with several occurrences of certain type template<class> class Decor, returns the type without the appearances of the class Decorator.
An example would be to convert following type
A<Decor<T<B<A<Decor<C>>>>>>
into
A<T<B<A<C>>>>
We assume that the structure of the final type is indeed a correct type, but we do not assume anything on the structure of the input type. It could be the case that some types used to construct the input type were of the form template<class...> class or any other type class.
You can use a class template and a couple of specializations like these:
template<typename T>
struct RemDec {
using type = T;
};
template<template<typename...> class C, typename... T>
struct RemDec<C<T...>> {
using type = C<typename RemDec<T>::type...>;
};
template<typename T>
struct RemDec<Decorator<T>> {
using type = typename RemDec<T>::type;
};
The class template helps to stop iterating over your chain of types.
The first specialization memorizes a class template and helps cleaning up what remains.
The last specialization removes the Decorator detected and goes on analyzing what remains.
It follows a minimal, working example:
#include<type_traits>
template<typename>
struct Decorator {};
template<typename...>
struct S {};
template<typename T>
struct RemDec {
using type = T;
};
template<template<typename...> class C, typename... T>
struct RemDec<C<T...>> {
using type = C<typename RemDec<T>::type...>;
};
template<typename T>
struct RemDec<Decorator<T>> {
using type = typename RemDec<T>::type;
};
int main() {
static_assert(std::is_same<
typename RemDec<S<Decorator<S<S<Decorator<S<int>>>>>, Decorator<S<double>>>>::type,
S<S<S<S<int>>>, S<double>>
>::value, "!");
}
As you can see by running it, any instance of Decorator is removed from the original type.
template <class T>
struct RemDec
{ using type = T; };
template <class T>
struct RemDec<Decor<T>>
{ using type = T; };
template <class T>
struct RemDec<T&>
{ using type = typename RemDec<T>::type&; };
template <class T>
struct RemDec<T&&>
{ using type = typename RemDec<T>::type&&; };
template <class T>
struct RemDec<const T>
{ using type = typename RemDec<T>::type const; };
template <class T>
struct RemDec<volatile T>
{ using type = typename RemDec<T>::type volatile; };
template <template <typename...> class TT, class... Ts>
struct RemDec<TT<Ts...>>
{ using type = TT<typename RemDec<Ts>::type...>; }
You will need even more specializations if your templates might have value- or template-template-arguments.
Is there a way to extract a partial default specialization from the compiler?
Say that I have this two parameter template:
template<typename A, typename B>
struct X {
A a;
B b;
};
and I also have some code that makes use of a single parameter template, like this:
template<template<typename> class T, typename B>
struct make_T_of_B {
T<B> member;
};
I'd like to be able to say:
make_T_of_B<X<int>, double> dummy;
where X<int> is taken as a single parameter template. It would be equivalent to this template:
template<typename B>
struct Y {
int a;
B b;
};
which looks like how one would specialize X<int, B> without actually changing anything. It's in a way similar to a default specialization -- except that a default specialization doesn't produce another template but rather an actual type (in other words, it's always total).
I realize that I can cascade the template arguments
template<typename A>
struct Z1 {
// start from scratch
template<typename B>
struct Z2 {
A a;
B b;
};
// inherit from double template above
template<typename B>
struct X: ::X<A, B> {};
};
make_T_of_B<Z1<int>::Z2, double> dummy1;
make_T_of_B<Z1<int>::X, double> dummy2;
but I find that to be rather hard to read and not communicate my intentions clearly.
Thank you.
I misunderstood your question. All you want is a way to bind the first template parameter, which you can do easily like this:
template <typename T> using Foo = X<int, T>;
Now Foo<double> is the same as X<int, double>.
Without C++11-style aliases, you can achieve the same with a bit more boilerplate:
template <typename T> struct Foo
{
typedef X<int, T> type;
};
Now you use Foo<double>::type.
I'd use a trait:
template <typename> struct applicator;
template <template <typename> class Tmpl, typename T>
struct applicator<Tmpl<T>>
{
template <typename A>
using rebind = make_T_of_B<Tmpl, A>;
};
Now you can say:
applicator<X<int>>::rebind<double> dummy;
You can of course also move the second argument, A, into the main template:
template <typename, typename> bpplicator;
template <template <typename> class Tmpl, typename T, typename A>
struct bpplicator<Tmpl<T>, A>
{
using type = make_T_of_B<Tmpl, A>; // or "typedef make_T_of_B<Tmpl, A> type;"
};
bpplicator<X<int>, double>::type dummy;
This has the advantage that it works in C++03, too.
Having a class like the A, is there a way to apply it to a template like this of B, with T2 set to some type C? But without creating another template class inheriting from A.
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
With C++11 using a template alias works:
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
class C
{ };
template< typename T > using A1 = A< T, C >;
int main()
{
B< A1 > b;
}
without C++11, you are left with what you probably already know:
template< typename T > class A1 : A< T, C > {};
I will propose an alternative solution: do not use template template parameters.
If you write:
template <typename T> struct B {};
Then it can be used with A<int, int> or C<3> or even plain D.
Whilst it is possible to use template template parameters, it is general a bad idea. You should treat the template parameter of a class as an implementation detail and apply the golden rule: do not rely on implementation details.
If you need access to the type, somehow, then use an associated type (aka T::AssociatedType) or a trait (BTraits<T>::AssociatedType).
EDIT: dealing with multiple instantiations of the template template parameter.
Suppose we want to "erase" the template template parameter of such a class:
template <template <typename> class A>
struct Something {
template <typename T>
void doit() { A<T>::doit(); }
};
The C++ standard allocation model is to use an inner rebind structure:
template <typename T>
struct Simple {
template <typename U>
struct rebind { typedef Simple<U> type; };
};
template <typename T0, typename T1>
struct Multi {
template <typename U>
struct rebind { typedef Multi<U, T1> type; };
};
template <typename A>
struct Something {
template <typename T>
void doit() { typedef typename A::rebind<T>::type B; B::doit(); }
};
Note how you can use complex computations in rebind and nothing forces you in blindly passing the type received as parameter.
Whilst another (similar) solution is to ask for a factory (aka, the object passed itself cannot be used but it can build useful objects); for ease of use the C++ containers ask of their allocators that they be both usable in themselves and factories for other types.
Yes, you can do it using C++11's alias template:
template <typename T>
using AA = A<T, C>;
B<AA> b;
Live example
Consider the following class, with the inner struct Y being used as a type, eg. in templates, later on:
template<int I>
class X{
template<class T1>
struct Y{};
template<class T1, class T2>
struct Y{};
};
Now, this example will obviously not compile, with the error that the second X<I>::Y has already been defined or that it has too many template parameters.
I'd like to resolve that without (extra) partial specialization, since the int I parameter isn't the only one and the position of it can differ in different partial specializations (my actual struct looks more like this, the above is just for simplicity of the question), so I'd like one class fits every I solution.
My first thought was obviously enable_if, but that seems to fail on me, eg. I still get the same errors:
// assuming C++11 support, else use boost
#include <type_traits>
template<int I>
class X{
template<class T1, class = std::enable_if<I==1>::type>
struct Y{};
template<class T1, class T2, class = std::enable_if<I==2>::type>
struct Y{};
};
So, since enable_if fails, I hope there is another way to achieve the following compile time check:
template<int I>
class X{
__include_if(I == 1){
template<class T1>
struct Y{};
}
__include_if(I == 2){
template<class T1, class T2>
struct Y{};
}
};
It would just be to save me a lot of code duplication, but I'd be really happy if it was somehow possible.
Edit: Sadly, I can't use the obvious: variadic templates, as I'm using Visual Studio 2010, so only the C++0x stuff that is supported there I can use. :/
There are two problems here:
enable_if works with partial specialization, not primary templates.
The number of externally-visible arguments is determined by the primary template, of which there may be only one.
Answer 1.
As you suggested in chat, a linked list of templates can emulate the variadic parameter pack.
template<int I>
class X{
template<class list, class = void>
struct Y;
template<class list>
struct Y< list, typename std::enable_if<I==1>::type > {
typedef typename list::type t1;
};
template<class list>
struct Y< list, typename std::enable_if<I==2>::type > {
typedef typename list::type t1;
typedef typename list::next::type t2;
};
};
If you end up with next::next::next garbage, it's easy to write a metafunction, or use Boost MPL.
Answer 2.
The different-arity templates can be named similarly but still stay distinct if they are nested inside the SFINAE-controlled type.
template<int I>
class X{
template<typename = void, typename = void>
struct Z;
template<typename v>
struct Z< v, typename std::enable_if<I==1>::type > {
template<class T1>
struct Y{};
};
template<typename v>
struct Z< v, typename std::enable_if<I==2>::type > {
template<class T1, class T2>
struct Y{};
};
};
X<1>::Z<>::Y< int > a;
X<2>::Z<>::Y< char, double > b;
Here you go:
http://ideone.com/AdEfl
And the code:
#include <iostream>
template <int I>
struct Traits
{
struct inner{};
};
template <>
struct Traits<1>
{
struct inner{
template<class T1>
struct impl{
impl() { std::cout << "impl<T1>" << std::endl; }
};
};
};
template <>
struct Traits<2>
{
struct inner{
template<class T1, class T2>
struct impl{
impl() { std::cout << "impl<T1, T2>" << std::endl; }
};
};
};
template<class T>
struct Test{};
template<class T, class K>
struct Foo{};
template<int I>
struct arg{};
template<
template<class, class> class T,
class P1, int I
>
struct Test< T<P1, arg<I> > >{
typedef typename Traits<I>::inner inner;
};
template<
template<class, class> class T,
class P2, int I
>
struct Test< T<arg<I>, P2 > >{
typedef typename Traits<I>::inner inner;
};
// and a bunch of other partial specializations
int main(){
typename Test<Foo<int, arg<1> > >::inner::impl<int> b;
typename Test<Foo<int, arg<2> > >::inner::impl<int, double> c;
}
Explanation: Basically it's an extension of the idea of partial specialization, however the difference is that rather than specializing within Test, delegate to a specific class that can be specialized on I alone. That way you only need to define versions of inner for each I once. Then multiple specializations of Test can re-use. The inner holder is used to make the typedef in the Test class easier to handle.
EDIT: here is a test case that shows what happens if you pass in the wrong number of template arguments: http://ideone.com/QzgNP
Can you try below (it is not partial specialization):
template<int I>
class X
{
};
template<>
class X<1>
{
template<class T1>
struct Y{};
};
template<>
class X<2>
{
template<class T1, class T2>
struct Y{};
};
I doubt if the answer is that simple !!
Edit (Mocking Partial specialization):
#Xeo, I was able to compile following code and seems to be fullfilling.
template<int I>
struct X
{
struct Unused {}; // this mocking structure will never be used
template<class T1, class T2 = Unused> // if 2 params passed-->ok; else default='Unused'
struct Y{};
template<class T1>
struct Y<T1, Unused>{}; // This is specialization of above, define it your way
};
int main()
{
X<1>::Y<int> o1; // Y<T1 = int, T2 = Unused> called
X<2>::Y<int, float> o2; // Y<T1 = int, T2 = float> called
}
Here, however you can use X<1>, X<2> interchangeably. But in the broader example you mentioned, that is irrelevant. Still if you need, you can put checks for I = 1 and I = 2.
How about this approach - http://sergey-miryanov.blogspot.com/2009/03/template-class-overriding.html? (sorry for russian)
You can use a meta function (here: inlined boost::mpl::if_c, but could be arbitrarily complex) to select the one you want. You need some scaffolding to be able to use constructors, though:
template <int I>
class X {
template <typename T1>
class YforIeq1 { /* meat of the class */ };
template <typename T1, typename T2>
class YforIeq2 { /* meat of the class */ };
public:
template <typename T1, typename T2=boost::none_t/*e.g.*/>
struct Y : boost::mpl::if_c<I==1,YforIeq1<T1>,YforIeq2<T1,T2> >::type {
typedef typename mpl::if_c<I==1,YforIeq1<T1>,YforIeq2<T1,T2> >::type YBase;
/* ctor forwarding: C++0x */
using YBase::YBase;
/* ctor forwarding: C++03 (runs into perfect fwd'ing problem)*/
Y() : YBase() {}
template <typename A1>
Y(const A1&a1) : YBase(a1) {}
template <typename A1, typename A2>
Y(const A1&a1, const A2&a2) : YBase(a1,a2) {}
// ...
};
};
If there's a problem with both YforIeqN being instantiated for each X, then you can try wrapping them as a nullary meta function (something along the way mpl::apply does) and use mpl::eval_if_c.