如何使用C++ 14和C++ 1z中的功能缩短这个可变参数模板代码?

syn*_*gma 10 c++ template-meta-programming variadic-templates c++14 c++17

这是一个代码片段,我将使用它来检查可变参数模板类型是否是唯一的:

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, "!");
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用C++ 14和C++ 1z中引入的功能使这段代码更短和/或更简洁?或者是否有更好的方法来使用新功能实现相同的效果?

在C++ 1z的情况下,我的意思是:最新版本的Clang和GCC中已有的功能.

Jon*_*ely 9

我们最近将std :: disjunction添加到了C++ 1z草案中,它可以用于is_one_of(并且一旦找到匹配就停止实例化,请参阅链接以获取更多详细信息):

template <typename F, typename... T>
  using is_one_of = std::disjunction<is_same<F, T>...>;
Run Code Online (Sandbox Code Playgroud)

这已在GCC主干中实现.对于旧版本的GCC,您可以使用实现细节__or_:

template <typename F, typename... T>
  using is_one_of = std::__or_<is_same<F, T>...>;
Run Code Online (Sandbox Code Playgroud)

或者disjunction使用C++ 11工具手动实现,如上面链接的提案末尾所示.


Pio*_*cki 6

#include <type_traits>

template <typename F, typename... Ts>
constexpr bool is_one_of = (std::is_same<F, Ts>{} || ...);

template <typename...>
constexpr bool is_unique = true;

template <typename F, typename... Ts>
constexpr bool is_unique<F, Ts...> = is_unique<Ts...> && !is_one_of<F, Ts...>;
Run Code Online (Sandbox Code Playgroud)

DEMO