Quantcast

[hana] create aribtrary tuples of integral_constants

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[hana] create aribtrary tuples of integral_constants

Daniel James via Boost-users

class StrConst
{
public:
    template<size_t N>
    constexpr StrConst(const char (&str)[N])
        : str_(str)
        , len_(N - 1)
    {
        static_assert(N > 1, "not a string");
    }

    constexpr operator const char*() const
    {
        return str_;
    }

    constexpr size_t size() const
    {
        return len_;
    }

    constexpr char operator[] (size_t i) const
    {
        return i < len_ ? str_[i] : throw std::out_of_range("invalid index");
    }

private:
    const char* const str_;
    const size_t      len_;
};

I have another constexpr function which returns the position of the first caret found in a string, starting from position n:

constexpr int caretPos(const StrConst& str, size_t n = 0)
{
    if (n == str.size())
        return -1;

    if (str[n] == '^')
        return n;

    return caretPos(str, n+1);
}

I can use the results of caretPos to create a typedef for a std::tuple of std::integral_constants, where the size of the tuple is the number of carets found in the string, and each tuple element is an integral constant whose value is the position of the caret in the string.

Here I manually construct this tuple:

int main()
{
    constexpr StrConst s("hello^world^");

    constexpr int pos1 = caretPos(s);
    constexpr int pos2 = caretPos(s, pos1+1);

    using P1 = std::integral_constant<int, pos1>;
    using P2 = std::integral_constant<int, pos2>;

    using PosTuple = std::tuple<P1, P2>;

    static_assert(std::tuple_element_t<0, PosTuple>::value == 5, "");
    static_assert(std::tuple_element_t<1, PosTuple>::value == 11, "");
}

Question:

I would now like to generalise this for any input string with any number of carets.

template<size_t... Ns>
using PosTuple = std::tuple<std::integral_constant<int, Ns>...>;

How can I generate the sequence of Ns... required here using caretPos or some other means?

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [hana] create aribtrary tuples of integral_constants

Daniel James via Boost-users
I’m not clear why hana is mentioned in the title.. So I might have misunderstood the question..

If what you want is a function which takes a StrConst as an argument and returns a PosTuple<...>, I don’t think there’s a way to do that. Since a StrConst loses its constexpr-ness as soon as it’s passed as an argument, the function’s return type (PosTuple<...>) cannot be deduced from it.

If you’re not sticked to functions, I think it’s possible to traverse the characters in StrConst one-by-one, and build the tuple on-the-fly.

Here’s my code, hope it helps: https://godbolt.org/g/aAcdjS

> On 10 Apr 2017, at 09:01, Steve Lorimer via Boost-users <[hidden email]> wrote:
>
> Making use of Scott Schurr's str_const (https://github.com/boostcon/cppnow_presentations_2012/blob/master/wed/schurr_cpp11_tools_for_class_authors.pdf?raw=true) I have a constexpr string.
>
> class StrConst
> {
> public:
>     template<size_t N>
>     constexpr StrConst(const char (&str)[N])
>         : str_(str)
>         , len_(N - 1)
>     {
>         static_assert(N > 1, "not a string");
>     }
>
>     constexpr operator const char*() const
>     {
>         return str_;
>     }
>
>     constexpr size_t size() const
>     {
>         return len_;
>     }
>
>     constexpr char operator[] (size_t i) const
>     {
>         return i < len_ ? str_[i] : throw std::out_of_range("invalid index");
>     }
>
> private:
>     const char* const str_;
>     const size_t      len_;
> };
>
> I have another constexpr function which returns the position of the first caret found in a string, starting from position n:
>
> constexpr int caretPos(const StrConst& str, size_t n = 0)
> {
>     if (n == str.size())
>         return -1;
>
>     if (str[n] == '^')
>         return n;
>
>     return caretPos(str, n+1);
> }
>
> I can use the results of caretPos to create a typedef for a std::tuple of std::integral_constants, where the size of the tuple is the number of carets found in the string, and each tuple element is an integral constant whose value is the position of the caret in the string.
>
> Here I manually construct this tuple:
>
> int main()
> {
>     constexpr StrConst s("hello^world^");
>
>     constexpr int pos1 = caretPos(s);
>     constexpr int pos2 = caretPos(s, pos1+1);
>
>     using P1 = std::integral_constant<int, pos1>;
>     using P2 = std::integral_constant<int, pos2>;
>
>     using PosTuple = std::tuple<P1, P2>;
>
>     static_assert(std::tuple_element_t<0, PosTuple>::value == 5, "");
>     static_assert(std::tuple_element_t<1, PosTuple>::value == 11, "");
> }
>
> Question:
>
> I would now like to generalise this for any input string with any number of carets.
>
> template<size_t... Ns>
> using PosTuple = std::tuple<std::integral_constant<int, Ns>...>;
>
> How can I generate the sequence of Ns... required here using caretPos or some other means?
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Loading...