Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a return constexpr pair for template instantiation

I am trying to use data from a std::pair that is returned by a constexpr free function. The first element determines the size of a std::array while the second element is stored in the array.

using DataBundle = std::pair<int, std::pair<int, int>>;

constexpr DataBundle get_data()
{
    // other work carried out here
    return std::make_pair(1, std::make_pair(2, 3));
}

struct x
{
    template<int size>
    using OtherData = std::array<std::pair<int, int>, size>;

    static constexpr OtherData<get_data().first> foo { get_data().second };
};

The above code isn't as efficient as it could be, as get_data() is called twice in the instantiation of foo. One solution could be to store the returned data as a member of the struct x, as shown below.

// previous code remains the same

struct x
{
    template<int size>
    using OtherData = std::array<std::pair<int, int>, size>;

    static constexpr DataBundle foo_bundle = get_data(); 
    static constexpr OtherData<foo_bundle.first> foo { foo_bundle.second };
};

Although this solution doesn't seem to take full advantage of the template mechanism. So my question is if there is a better approach to this that gets the best out of each of the above samples?

like image 342
manderc3 Avatar asked Jan 29 '26 22:01

manderc3


1 Answers

Indeed constexpr function might be computed several times (whereas template class should be instantiated only once), for trivial case as your, first snippet would be fine.

I would create dedicated function/lambda to create foo though:

struct x
{
    template<int size>
    using OtherData = std::array<std::pair<int, int>, size>;

    static constexpr auto foo = []() {
        constexpr DataBundle foo_bundle = get_data(); 

        return OtherData<foo_bundle.first>{foo_bundle.second};
    } ();
};
like image 53
Jarod42 Avatar answered Feb 01 '26 10:02

Jarod42