FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Adding static const rank to allow sfinae based on rank by tdegeus · Pull Request #2138 · xtensor-stack/xtensor · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .cpp  (1) .hpp  (5) .rst  (2) .txt  (1) All 4 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
1 change: 1 addition & 0 deletions docs/source/index.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ for details.
missing
histogram
random
sfinae
file_loading
build-options
pitfall
Expand Down
77 changes: 77 additions & 0 deletions docs/source/sfinae.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht

Distributed under the terms of the BSD 3-Clause License.

The full license is in the file LICENSE, distributed with this software.

.. _histogram:

SFINAE
======

Rank overload
-------------

All `xtensor`'s classes have a member ``rank`` that can be used
to overload based on rank using *SFINAE*.
Consider the following example:

.. code-block:: cpp

template <class E, std::enable_if_t<!xt::has_rank_t<E, 2>::value, int> = 0>
inline E foo(E&& a)
{
... // act on object of flexible rank, or fixed rank != 2
}

template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
inline E foo(E&& a)
{
... // act on object of fixed rank == 2
}

TEST(sfinae, rank_basic)
{
xt::xarray<size_t> a = {{9, 9}, {9, 9}};
xt::xtensor<size_t, 1> b = {9, 9};
xt::xtensor<size_t, 2> c = {{9, 9}, {9, 9}};

foo(a); // flexible rank -> first overload
foo(b); // fixed rank == 2 -> first overload
foo(c); // fixed rank == 2 -> second overload
}

.. note::

If one wants to test for more than a single value for ``rank``,
one can use the default value ``SIZE_MAX`` used for flexible rank objects.
For example, one could have the following overloads:

.. code-block:: cpp

// flexible rank
template <class E, std::enable_if_t<xt::has_rank_t<E, SIZE_MAX>::value, int> = 0>
inline E foo(E&& a);

// fixed rank == 1
template <class E, std::enable_if_t<xt::has_rank_t<E, 1>::value, int> = 0>
inline E foo(E&& a);

// fixed rank == 2
template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
inline E foo(E&& a);

Note that fixed ranks other than 1 and 2 will raise a compiler error.

Of course, if one wants a more limited scope, one could also do the following:

.. code-block:: cpp

// flexible rank
inline void foo(xt::xarray<double>& a);

// fixed rank == 1
inline void foo(xt::xtensor<double,1>& a);

// fixed rank == 2
inline void foo(xt::xtensor<double,2>& a);
1 change: 1 addition & 0 deletions include/xtensor/xarray.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ namespace xt
using inner_backstrides_type = typename base_type::inner_backstrides_type;
using temporary_type = typename semantic_base::temporary_type;
using expression_tag = Tag;
constexpr static std::size_t rank = SIZE_MAX;

xarray_container();
explicit xarray_container(const shape_type& shape, layout_type l = L);
Expand Down
7 changes: 4 additions & 3 deletions include/xtensor/xfixed.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace xt
namespace detail
{
/**************************************************************************************
The following is something we can currently only dream about -- for when we drop
The following is something we can currently only dream about -- for when we drop
support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)

template <class T>
Expand Down Expand Up @@ -281,7 +281,7 @@ namespace xt
* with tensor semantic and fixed dimension
*
* @tparam ET The type of the elements.
* @tparam S The xshape template paramter of the container.
* @tparam S The xshape template paramter of the container.
* @tparam L The layout_type of the tensor.
* @tparam SH Wether the tensor can be used as a shared expression.
* @tparam Tag The expression tag.
Expand Down Expand Up @@ -313,6 +313,7 @@ namespace xt
using expression_tag = Tag;

constexpr static std::size_t N = std::tuple_size<shape_type>::value;
constexpr static std::size_t rank = N;

xfixed_container() = default;
xfixed_container(const value_type& v);
Expand Down Expand Up @@ -616,7 +617,7 @@ namespace xt

/**
* Allocates an xfixed_container with shape S with values from a C array.
* The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for ``xt::xshape<X, Y, Z>``.
* The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for ``xt::xshape<X, Y, Z>``.
* C arrays can be initialized with the initializer list syntax, but the size is checked at compile
* time to prevent errors.
* Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime.
Expand Down
3 changes: 2 additions & 1 deletion include/xtensor/xtensor.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace xt
using inner_strides_type = typename base_type::inner_strides_type;
using temporary_type = typename semantic_base::temporary_type;
using expression_tag = Tag;
constexpr static std::size_t rank = N;

xtensor_container();
xtensor_container(nested_initializer_list_t<value_type, N> t);
Expand Down Expand Up @@ -759,7 +760,7 @@ namespace xt
std::fill(m_storage.begin(), m_storage.end(), e);
return *this;
}

template <class EC, std::size_t N, layout_type L, class Tag>
inline auto xtensor_view<EC, N, L, Tag>::storage_impl() noexcept -> storage_type&
{
Expand Down
13 changes: 13 additions & 0 deletions include/xtensor/xutils.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,19 @@ namespace xt

template <class ST>
using inner_reference_t = typename inner_reference<ST>::type;

/************
* has_rank *
************/

template <class E, size_t N>
struct has_rank
{
using type = std::integral_constant<bool, std::decay_t<E>::rank == N>;
};

template <class E, size_t N>
using has_rank_t = typename has_rank<std::decay_t<E>, N>::type;
}

#endif
1 change: 1 addition & 0 deletions include/xtensor/xview.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ namespace xt

using container_iterator = pointer;
using const_container_iterator = const_pointer;
constexpr static std::size_t rank = SIZE_MAX;

// The FSL argument prevents the compiler from calling this constructor
// instead of the copy constructor when sizeof...(SL) == 0.
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ set(XTENSOR_TESTS
test_extended_xhistogram.cpp
test_extended_xsort.cpp
test_xchunked_array.cpp
test_sfinae.cpp
)

if(nlohmann_json_FOUND)
Expand Down
90 changes: 90 additions & 0 deletions test/test_sfinae.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* Copyright (c) QuantStack *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include <complex>
#include <limits>

#include "gtest/gtest.h"
#include "xtensor/xtensor.hpp"
#include "xtensor/xarray.hpp"
// #include "xtensor/xfixed.hpp"
#include "xtensor/xview.hpp"

namespace xt
{
template <class E, std::enable_if_t<!xt::has_rank_t<E, 2>::value, int> = 0>
inline E sfinae_rank_basic_func(E&& a)
{
E b = a;
b.fill(0);
return b;
}

template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
inline E sfinae_rank_basic_func(E&& a)
{
E b = a;
b.fill(2);
return b;
}

TEST(sfinae, rank_basic)
{
xt::xarray<size_t> a = {{9, 9, 9}, {9, 9, 9}};
xt::xtensor<size_t, 1> b = {9, 9};
xt::xtensor<size_t, 2> c = {{9, 9}, {9, 9}};
// xt::xtensor_fixed<size_t, xt::xshape<2, 2>> d = {{9, 9}, {9, 9}};
auto v = xt::view(c, 0, xt::all());

EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_basic_func(a), 0ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_basic_func(b), 0ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_basic_func(c), 2ul)));
// EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_basic_func(d), 2ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_basic_func(v), 0ul)));
}

template <class E, std::enable_if_t<xt::has_rank_t<E, SIZE_MAX>::value, int> = 0>
inline E sfinae_rank_func(E&& a)
{
E b = a;
b.fill(0);
return b;
}

template <class E, std::enable_if_t<xt::has_rank_t<E, 1>::value, int> = 0>
inline E sfinae_rank_func(E&& a)
{
E b = a;
b.fill(1);
return b;
}

template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
inline E sfinae_rank_func(E&& a)
{
E b = a;
b.fill(2);
return b;
}

TEST(sfinae, rank)
{
xt::xarray<size_t> a = {{9, 9, 9}, {9, 9, 9}};
xt::xtensor<size_t, 1> b = {9, 9};
xt::xtensor<size_t, 2> c = {{9, 9}, {9, 9}};
// xt::xtensor_fixed<size_t, xt::xshape<2, 2>> d = {{9, 9}, {9, 9}};
auto v = xt::view(c, 0, xt::all());

EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_func(a), 0ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_func(b), 1ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_func(c), 2ul)));
// EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_func(d), 2ul)));
EXPECT_TRUE(xt::all(xt::equal(sfinae_rank_func(v), 0ul)));
}
}

Back | FazBrowse Home | New Git URL