This is a code snippet that I am going to use in order to check whether the variadic template types are unique:
template <typename...>
struct is_one_of;
template <typename F>
struct is_one_of<F> {
static constexpr bool value = false;
};
template <typename F, typename S, typename... T>
struct is_one_of<F, S, T...> {
static constexpr bool value =
std::is_same<F, S>::value || is_one_of<F, T...>::value;
};
template <typename...>
struct is_unique;
template <>
struct is_unique<> {
static constexpr bool value = true;
};
template <typename F, typename... T>
struct is_unique<F, T...> {
static constexpr bool value =
is_unique<T...>::value && !is_one_of<F, T...>::value;
};
int main() {
constexpr bool b = is_unique<bool, int, double>::value;
constexpr bool c = is_unique<int, char, int>::value;
static_assert(b == true && c == false, "!");
}
Is there any way to make this code shorter and/or more concise using features introduced in C++14 and C++1z? Or is there a better way to achieve the same effect using the new features?
In the case of C++1z I mean: features that are already available in the newest versions of Clang and GCC.
I'm in line with Brian Rodriguez's and Piotr Scontnincki's answers, as far as it concerns the fold expressions part. Until folding expressions are in, you could shrink the existing code a little bit by getting rid of the incomplete primary templates as follows:
We recently added std::disjunction to the C++1z draft, which can be used for
is_one_of
(and it stops instantiating as soon as it finds a match, see the link for more details):This is already implemented in GCC trunk. For older versions of GCC you can use the implementation detail
__or_
instead:Or implement
disjunction
by hand using C++11 facilities, as shown at the end of the proposal linked to above.DEMO
I'd (now) suggest using the
std::conj/disj/nega
family of STL functions:When fold-expressions, which were designed for these cases, are released into the language this will become trivial: