template specialization with struct in c++14 - c++14

I am trying to write a specialized decay with template specialization on certain types:
template <typename T>
struct stateful_decay {
using type = T;
};
template <typename T>
struct stateful_decay<T&&> {
using type = T;
};
template <>
struct stateful_decay<PullTask&&> {
using type = PullTask;
};
template <>
struct stateful_decay<PullTask&> {
using type = PullTask;
};
template <>
struct stateful_decay<PullTask> {
using type = PullTask;
};
template <>
struct stateful_decay<const PullTask&&> {
using type = PullTask;
};
template <>
struct stateful_decay<const PullTask&> {
using type = PullTask;
};
template <>
struct stateful_decay<const PullTask> {
using type = PullTask;
};
template <typename T>
using stateful_decay_t = typename stateful_decay<T>::type;
Apparently, PullTask specialization has a lot of verbosity. Basically, any thing related to PullTask type should decay to PullTask. Is there any way to improve this? I am thinking about to use std::decay_t but didn't know how to do so.

#include <type_traits>
template <typename T>
struct stateful_decay
: std::conditional<std::is_same<PullTask, std::decay_t<T>>{}, PullTask, T> {};
template <typename T>
struct stateful_decay<T&&>
: stateful_decay<T> {};
template <typename T>
using stateful_decay_t = typename stateful_decay<T>::type;
DEMO

Related

Idiom for default initialization depending on type

I have a template class that takes default member values.
template<class T = std::string>
struct A{
T val = {"val"};
};
However sometimes the default values do not make sense, for example:
A<int> a1; // cannot initialize int from "val"
Is there is good idiom to handle this issue?
I came up with this solution, which is quite verbose.
template<class T, class TT>
auto valid_or_default(TT&& other) ->
decltype(T{std::forward<TT>(other)}){return T{std::forward<TT>(other)};}
template<class T>
auto value_of_default(...){return T{};}
template<class T = std::string>
struct A{
T val = valid_or_default<T>("val");
};
(The other option is to set up a Boost.Fusion map to have a default value per type, but it is even more code and all the cases need to be handled.)
Update (thanks #Someprogrammerdude):
Another alternative for very specific cases (no valid based on syntax) can be done by specializing the constructor:
template<class T = std::string>
struct A{
T val;// = valid_or_default<T>("val");
A() : val{}{}
};
template<> A<std::string>::A() : val{"val"}{}
I still don't know what the original problem you try to solve is, or why you need to use a compile-time fixed-value for the initialization, but as it seems your structure is an aggregate you could simply use aggregate initialization:
template<typename T = std::string>
struct A
{
T val;
};
// ...
A a = { "val" };
A<int> b = { 1 };
Here is a C++17 solution:
template<class T, class TT>
auto valid_or_default(TT&& other)
{
if constexpr (std::is_constructible_v<T, TT>)
return T{std::forward<TT>(other)};
else
return T{};
}
Here's another option.
template <typename T>
T get_default_value()
{
return {};
}
template <>
std::string get_default_value<std::string>()
{
return "val";
}
template<class T = std::string>
struct A {
T val = get_default_value<T>();
};

Trailing return type usage when using CRTP

The following is a mockup code that I wrote to experiment with trailing return types in a CRTP setup.
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
struct t_aspect{
struct t_param1 {};
};
// Generic Selector
template <typename t_detail>
struct Select;
template <>
struct Select<t_aspect::t_param1> {
using typeof = t_aspect::t_param1;
};
//Base CRTP class
template<typename dclas>
class CrtpB
{
public:
template<typename T1>
auto func1() -> // What should be here?
{
return(static_cast<dclas*>(this)->func1<T1>());
}
};
//Derived CRTP class
class CrtpD : public CrtpB<CrtpD>
{
private:
uint32_t param1 = 0;
private:
auto func1(const t_aspect::t_param1&) -> uint32_t
{
return(param1);
}
public:
static auto create() -> unique_ptr<CrtpB>
{
return(unique_ptr<CrtpD>(new CrtpD));
}
template<typename T1>
auto func1() -> decltype(func1(typename Select<T1>::typeof()))
{
return(func1(typename Select<T1>::typeof()));
}
};
int main()
{
auto crtp = CrtpD::create();
auto parm = crtp->func1<t_aspect::t_param1>();
return 0;
}
I would like some help in deciphering what should be the trailing return type of func1 in CrtpB.
I have tried using
decltype(static_cast<dclas*>(this)->func1<T1>())
but this does not work. I have also tried writing a helper function based on a solution found in Inferring return type of templated member functions in CRTP.
template <typename D, typename T>
struct Helpr {
typedef decltype(static_cast<D*>(0)->func1<T>()) type;
};
But this does not work either.
dclas is an incomplete type when the base class is instantiated. You need to do two things to make this work:
Defer the checking of the type of func1<T1>() until the type is complete
Use the template keyword on the dependent expression so that the template definition is parsed correctly:
We can do this by adding a layer of indirection:
namespace detail {
template <class T, class Func1Arg>
struct func1_t {
using type = decltype(std::declval<T>().template func1<Func1Arg>());
};
};
Then you use this trait as the trailing return type:
template<typename T1>
auto func1() -> typename detail::func1_t<dclas,T1>::type
{
return(static_cast<dclas*>(this)->template func1<T1>());
}

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> {};
}

Using of types that was defined inside a template class

I want to use a type that was defined inside a template class. How can I do it?
template < typename A, typename B>
struct internal {
const static std::string value;
typedef B type;
};
template < typename A > using external = struct internal<A, int>;
external::type object;

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;
};

Resources