I'm trying to use std::disjuction
to test whether a parameter pack contains std::wstring
, and nothing I've tried seems to want to make it return the value I'm expecting.
Here's the code as it is currently (https://godbolt.org/z/x99M8avYE):
#include <string>
#include <iostream>
#include <type_traits>
template <typename ...Ts>
using HasWS = std::disjunction<std::is_same<std::wstring,Ts>...>;
template <typename T, typename ...Ts>
using HasWS2 = std::disjunction<std::is_same<T,Ts>...>;
template<typename... Args>
void f(Args&&... args) {
std::cout << HasWS<Args...>::value << std::endl;
std::cout << HasWS2<std::wstring, Args...>::value << std::endl;
std::cout << std::disjunction_v<std::is_same<std::wstring, Args>...> << std::endl;
(std::cout << typeid(args).name() << std::endl, ...);
}
template <typename T, typename ...Ts>
using areT = std::disjunction<std::is_same<T,Ts>...>;
int main() {
std::wstring wstr(L"abc");
std::string str("def");
static_assert(areT<std::wstring,std::string,std::wstring>::value);
static_assert(HasWS<std::wstring,decltype(wstr),decltype(str)>::value);
static_assert(std::is_same<decltype(wstr), std::wstring>::value);
f(wstr, str);
f(str, str);
f(wstr, wstr);
std::cout << std::is_same_v<decltype(wstr), std::wstring> << std::endl;
return 0;
}
As you can see, I was experimenting with different ways to call disjuction
but none of them would find the wstring
and return true. I even stooped as low as printing out the types for each of the elements in the pack and using is_same
to make sure that wstr
was actually a wstring
.
What the heck is going on? Is it something to do with the pack argument to the template that I'm just not aware of?
CodePudding user response:
Note that the parameter type received by f
is forwarding reference Args&&
, so when you pass in an lvalue wstr
, Args
will be instantiated as std::wstring&
instead of std::wstring
, you should remove the reference, e.g.
template<typename... Args>
void f(Args&&... args) {
std::cout << HasWS<std::remove_reference_t<Args>...>::value << std::endl;
std::cout << HasWS2<std::wstring, std::remove_reference_t<Args>...>::value << std::endl;
std::cout << std::disjunction_v<std::is_same<std::wstring, std::remove_reference_t<Args>>...> << std::endl;
}