c++ 是否有办法找到std::tuple元素是否都是相同类型的?

p4tfgftt  于 2023-05-02  发布在  其他
关注(0)|答案(4)|浏览(166)

我想根据std::tuple中的所有元素是否为相同类型来判断true / false。
例如

std::tuple<int, int, int> t = { 1, 1, 1};
auto A = all_same(t);

std::tuple<int, float, int> t = { 1, 1.0, 1};
auto B = all_same(t);

这里,A为真,B为假
无论如何要做到这一点?

jei2mxaa

jei2mxaa1#

C++17解决方案与折叠表达式:

#include <tuple>

template<typename Head, typename...Tail>
constexpr bool all_same(const std::tuple<Head,Tail...>&){
    return (std::is_same_v<Head,Tail> && ...);
}

constexpr bool all_same(const std::tuple<>&){
    return true; // This is reasonable, right?
}

int main() {
            std::tuple<int, int, int> t1{ 1, 1, 1};
          static_assert(all_same(t1));

          std::tuple<int, float, int> t2{ 1, 1.0f, 1};
          static_assert(!all_same(t2));
          std::tuple<> t3{};
          static_assert(all_same(t3));
}

也许你想使用std::is_same_v的替代品/补充:

  • std::is_convertible,尽管您应该检查这两对,因为它不是对称的。
  • std::swappable在这个意义上可能是is_convertible的对称版本。
  • 如果希望const float&float被视为相等,则添加std::decay
xxslljrj

xxslljrj2#

std::tuple<A,B,C,D>std::tuple<B,C,D,A>是相同类型时,元组std::tuple<A,B,C,D>的类型都相同。

#include <type_traits>
#include <tuple>
#include <iostream>

template <typename First, typename... T>
struct all_same_type {
    constexpr static bool value = std::is_same_v< std::tuple<First,T...>,
                                                  std::tuple<T...,First>>;
};

template <typename... T>
struct all_same_type<std::tuple<T...>> : all_same_type<T...> {};

template <typename... T>
constexpr bool all_same_type_v = all_same_type<T...>::value;

int main() {
    std::tuple<int, int, int> t = { 1, 1, 1};
    std::cout << all_same_type_v< decltype(t)> << "\n";

    std::tuple<int, float, int> u = { 1, 1.0, 1};
    std::cout << all_same_type_v< decltype(u)> << "\n";
}

Output

1
0
q9rjltbz

q9rjltbz3#

下面是使用fold expressionslambda expression的方法:

#include <tuple>
#include <iostream>

//for returning result based on both "type and value"
template<typename First, typename... Rest>
bool allSame(const std::tuple<First, Rest...> &tup ) requires(std::is_same_v<First, Rest> && ...)
{
    return std::apply([](const auto&... nth)
    {
        return (true == ... == nth  );
    }, tup);    
}
//version that always returns false if any type mismatch
template<typename First, typename... Rest>
bool allSame(const std::tuple<First, Rest...> &tup ) requires (... || !std::is_same_v<First, Rest>)
{    
    return false;
}

int main(){
    std::tuple<int, int, int> t = { 1, 1, 1};
    std::cout << allSame(t); //prints 1 

    std::tuple<int, float, int> t2 = { 1, 1.0, 1};
    std::cout << allSame(t2); //prints 0  

    std::tuple<int, int, int> t3 = { 1, 8, 1};
    std::cout << allSame(t3); //prints 0
}

Demo

备注

如果您不关心这些值,那么用return true;替换第一个模板的主体就很简单了,如下面的modified demo所示。

ilmyapht

ilmyapht4#

另一种变体:

template <typename... Ts>
struct all_same_type : std::bool_constant<[](){
        if constexpr (sizeof...(Ts) == 0) {
            return true;
        } else {
            using First = std::tuple_element_t<0, std::tuple<Ts...>>;
            return (std::is_same_v<First, Ts> && ...);
        }
    }()>
{
};

template <typename T>
struct all_same_inner_type;

template <typename... Ts>
struct all_same_inner_type<std::tuple<Ts...>> : all_same_type<Ts...> {};

template <typename...Ts>
constexpr bool all_same_inner_type_v = all_same_inner_type<Ts...>::value;

Demo

相关问题