This project is read-only.

Query result value / reference

Mar 17, 2014 at 1:08 PM
Dear all,

I have a database of objects, and I am using CPPLINQ to select some items based upon given properties. In order to spare some memory, I would like to know wether it possible for a CPPLINQ query to return elements by reference instead of by value ?
Mar 17, 2014 at 8:58 PM
cpplinq tries to return references when it's safe to do so but some operations (such as select) return by value.

Perhaps you can post some code and we can take a look to see if there's something we can do?

Mar 18, 2014 at 9:02 AM
Edited Mar 18, 2014 at 9:04 AM
Dear Marten,

I am using a vector of "Component" as a database, and I am using CPPLINQ to retrieve some "Component" based upon given properties. These properties does not changed as soon as the vector is built (by serialization from a binary file) - therefore, I would like to know how to make CPPLINQ return "Components" as const reference to avoid unnecessary copies and waste of memory. To give you a better insight, here are some sample code:

--> "Component" used to store informations
template<typename T>
class ComponentData
//Serialized Data
    // Scalar properties
    double m_MolecularWeight;
    double m_NormalBoilingPoint;
    double m_CriticalTemperature;
    double m_CriticalPressure;

    T Get_MolecularWeight() const
        return m_MolecularWeight;

    const std::string Get_CASN() const
        return m_CASN;
--> The database itself
template<typename T>
class ComponentDatabase
    ComponentDatabase(const ComponentDatabase& that) = delete;
        std::vector<ComponentData<T>> m_Database;

    ComponentDatabase(std::string a_PathToDB);  // The constructor will load data from a binarized file
        std::vector<ComponentData<T>> Find_MW(const T a_LowerMW, const T a_UpperMW) const;
--> Here's the detail of Find_MW:
template<typename T>
std::vector<ComponentData<T>> ComponentDatabase<T>::Find_MW(const T a_LowerMW, const T a_UpperMW) const
    return cpplinq::from(m_Database)
        >> cpplinq::where([a_LowerMW, a_UpperMW](ComponentData<DOUBLE> cmp){return cmp.Get_MolecularWeight() > a_LowerMW &&   cmp.Get_MolecularWeight() < a_UpperMW; })
        >> cpplinq::to_vector();
--> An example of CPPLINQ query:
auto cmps = vComponentDatabase.Find_MW(100.0, 101.1);  // I would like at this point to have a vector (or any else container) of ComponentData references.
Thank you for your support and giving us access to LINQ :)
Mar 19, 2014 at 8:35 PM

Been thinking. STL supports something called std::reference_wrapper<>. The intention of this is to wrap reference into a value type that can be stored in STL containers.

I introduced a new ref range operator that allows converting ranges into a range of std::reference_wrapper<>

For example:
            std::vector<std::reference_wrapper<customer const>> ref_result =
                    from_array (customers)
                >>  ref ()
                >>  to_vector ()

            auto index = 0U;
            for (auto customer : ref_result)
                if (!TEST_ASSERT (customers[index].id, customer.get ().id))
                    printf ("    @index:%u\n", index);


            TEST_ASSERT (count_of_customers, ref_result.size ());
This shouldn't invoke the .ctor of the customer class.

You can find the operator in the branch: mrange__ref_range

I need to verify that the ref range operator in the cpplinq supported compilers before I dare merge it into master but it would help me if you could verify that this solves your issue.

Mar 20, 2014 at 10:00 AM
Dear Marten,

I'm glad to say that using branch mrange__ref_range and ref() operator is working perfectly ! If you need me to test some features, please let me know.


Mar 20, 2014 at 2:49 PM
Thanks for testing. Glad it resolved your issue.

Note that the ref() operator is only valid after operators that return references (such as where()). ref() operator tests this with a static_assert in order to minimize the risk of doing it wrong.

As soon as I have this verified for our supported compilers I will merge this to master.

This probably warrants a new release of cpplinq as well (been holding that off long enough now).
Mar 20, 2014 at 8:10 PM

I read up on compiler support for reference wrapper.

I think it is safe to merge to master and have done so. So if you grab the latest from master you should have ref ()
Mar 21, 2014 at 11:34 AM
Hello Marten,

A quick word to say that master branch solved my issue under VisualStudioExpress 2013.

Mar 21, 2014 at 12:51 PM
Thanks good to know.
Mar 23, 2014 at 11:27 AM
Edited Mar 23, 2014 at 11:27 AM
FYI: There's a new release now:

This contains amongst other things the ref () range operator. I listed you in "Thanks to" section.

I've also updated the documentation to include ref ():

PS. Please rate the release (good or bad) after you tested it.