How to access an element of variadic pack in enable_if_t

Suppose I have a function template like this (this is not valid C++ - just for transmitting the idea):


template<class ...Ts>
std::enable_if_t< std::is_same<decltype(std::get<0>(Ts)), std::wstring>::value, std::string>
jdto_string(Ts&& ...ts)
{
std::ostringstream oss;
(oss << ... << std::forward<Ts>(ts)); // left fold
return oss.str();
}

How can I access the first element of the pack to see if it is a wstring and if so enable the instantiation?

Thanks
Juan
I don't know what you are doing and I am not an expert at meta template programming, but to create an interface which blends string and wstring and any string type together is to use something like this:

std::basic_string< char, std::char_traits< char>>

and swap out char with whatever you want, and wstring is simply this but with wchar_t.
Is it possible to test the type of any arbitrary element in the variadic pack in a function such as provided above?
I would like to create specializations of the function jdto_string based on the type of the nth template parameter.
It may sound useless - but it's an exercise.

Thanks
The easiest way to index a parameter pack is to build a tuple out of it and call std::tuple_element on it.

However, types in the pack probably need to have their reference-ness and cv-qualifications stripped before you can compare them easily. You could do that explicitly with a combination of remove_reference and remove_cv, or decay if you're not dealing with function or array types; or preferably C++20's remove_cvref.

1
2
3
4
5
6
7
8
9
10
11
template <typename... Ts>
std::enable_if_t<
  std::is_same_v<
    std::decay_t<
      std::tuple_element_t<0, std::tuple<Ts...>>>,
    std::wstring>,
  std::string>
jdto_string(Ts&&...)
{
  return "wstring first argument"; 
}


But forwarding functions are pesky because they have a tendency to be chosen when you don't want them to.
Last edited on
Couldn't you strip off the first type in the usual way?

 
template <typename T, typename...Ts>

But I guess that breaks up the pack.

BTW, what's the difference between enable_if and enable_if_t?
enable_if requires that you specify ::type to get the type while enable_if_t is an alias for enable_if<>::type.
So its convenience...
Thanks mbozzi for your excellent reply!
Couldn't you strip off the first type in the usual way?

Yeah, but in his second post @Juan Dent says he wants the type of an arbitrary element in the pack.

BTW, what's the difference between enable_if and enable_if_t?

Standard library meta-functions with a _t suffix are just type aliases for the member type named metafunction::type. For instance, std::enable_if_t is something like
1
2
template <bool Enable, typename T> 
using std::enable_if_t = typename std::enable_if<Enable, T>::type;


Same idea for the _v suffix. For instance,
1
2
template <typename T, typename U>
constexpr bool is_same_v = std::is_same<T, U>::value;


Thanks mbozzi for your excellent reply!

You're welcome!
Last edited on
> Couldn't you strip off the first type in the usual way?

One could. For instance:
1
2
3
4
5
6
7
template < std::size_t, typename... > struct type_at ;

template < std::size_t N, typename FIRST, typename... REST >
struct type_at<N,FIRST,REST...> : type_at< N-1, REST... > {} ;

template < typename FIRST, typename... REST >
struct type_at<0,FIRST,REST...> { using type = FIRST ; } ;

http://coliru.stacked-crooked.com/a/818edd66b5841f20
Topic archived. No new replies allowed.