xtensor icon indicating copy to clipboard operation
xtensor copied to clipboard

Unexpected value of `xt::get_rank<xt::xtensor_adaptor>`.

Open 1uc opened this issue 1 year ago • 1 comments

While using xt::get_rank to detect the rank of various XTensor objects, we noticed that the following test fails:

template <class EC, size_t N, xt::layout_type L, class Tag>
void check_adapt_tensor(xt::xtensor_adaptor<EC, N, L, Tag>& x) {
    REQUIRE(xt::get_rank<decltype(x)>::value == N);
}

TEST_CASE("xt::get_rank", "[xtensor]") {
    std::array<size_t, 3> shape{3, 2, 4};
    xt::xtensor<double, 3> a(shape);
    auto a_view = xt::adapt(a.data(), a.size(), xt::no_ownership(), shape);

    check_adapt_tensor(a_view);
}

Naively, this is unexpected, because xt::xtensor_adaptor to my understanding has a compile-time constant rank and N is one of the template arguments of the class. Which is different from xt::xarray_adaptor which doesn't have a compile-time constant rank.

1uc avatar May 16 '24 07:05 1uc

@1uc Decaying away the reference allows proper SFINAE of get_rank here:

    template <class E, typename = void>
    struct get_rank
    {
        static constexpr std::size_t value = SIZE_MAX;
    };

    template <class E>
    struct get_rank<E, decltype((void) E::rank, void())>
    {
        static constexpr std::size_t value = E::rank;
    };

This passes.

    template <class EC, size_t N, xt::layout_type L, class Tag>
    void check_adapt_tensor(xt::xtensor_adaptor<EC, N, L, Tag>& x) {
        REQUIRE(xt::get_rank<std::decay_t<decltype(x)>>::value == N);
    }

    TEST(xview, test_case) {
        std::array<size_t, 3> shape{3, 2, 4};
        xt::xtensor<double, 3> a(shape);
        auto a_view = xt::adapt(a.data(), a.size(), xt::no_ownership(), shape);

        check_adapt_tensor(a_view);
    }
}

spectre-ns avatar Dec 22 '24 20:12 spectre-ns