How can I avoid writing every permutation of L and R value references for a function which does not allow universal references?

Matt

This example code below is designed to express the need to achieve 2 goals on multiple instances of other code:

  1. Maintain full type specification in template function bar.
  2. Avoid writing all permutations of l-value and r-value references for bar.

As the number of parameters in the function bar grows, it becomes more difficult to define every permutation of l-value and r-value references.

Currently, I am not able to use r-value references in bar function.

Is there any method, that I'm not aware of? Or should I write every permutation as a last resort?

Godbolt

#include <iostream>
#include <vector>
// Skip down to the bar function

template<typename DT> struct X
{
    DT data;

    X(DT data) : data(data * 2) {}
    template<typename VT>
    float foo(VT value) { return data + value; }
};

template<typename DT> struct Y 
{
    DT data;

    Y(DT data) : data(data * 4) {}
    template<typename VT>
    float foo(VT value) { return value * data; }
};

template<typename DT> struct Z
{
    DT data;

    Z(DT data) : data(data * 8) {}
    template<typename VT>
    float foo(VT value) { return (value + 1) * (data + 1); }
};

// Function of interest
template <template<typename> typename XT, typename AT,
    template<typename> typename YT, typename BT,
    template<typename> typename ZT, typename CT>
float bar(XT<AT>&& a, YT<BT>&& b, ZT<CT>&& c) // Universal references are not allowed
{ 
    XT<float> a_result(b.data - c.data);
    YT<float> b_result(a.data - c.data);
    XT<float> c_result(a.data + b.data);

    return a_result.foo(a.data) + b_result.foo(b.data) + c_result.foo(c.data);
}

int main() 
{
    X<float> x(1.);
    Y<double> y(2.);
    Z<int> z(3);

    double result = bar(x, y, z);
    std::cout << result << std::endl;
}

The Godbolt output for the code above

Could not execute the program
Compiler returned: 1
Compiler stderr
<source>: In function 'int main()':
<source>:52:23: error: cannot bind rvalue reference of type 'X<float>&&' to lvalue of type 'X<float>'
   52 |   double result = bar(x, y, z);
      |                       ^
<source>:39:20: note:   initializing argument 1 of 'float bar(XT<AT>&&, YT<BT>&&, ZT<CT>&&) [with XT = X; AT = float; YT = Y; BT = double; ZT = Z; CT = int]'
   39 | float bar(XT<AT>&& a, YT<BT>&& b, ZT<CT>&& c) { // Universal references not allowed
      |           ~~~~~~~~~^
JeJo

In your shown simplified code, it seems like you need only const qualified l-value reference.

However, if you insist having the forwarding ref (àka. universal reference) been used instead, I recommend changing the template template parameters to be a simple template function as follows:

template <typename XT, typename YT, typename ZT>
auto bar(XT&& a, YT&& b, ZT&& c)
// uncomment the following if you want to restrict
// the rvalue references parameters been used (aka. SFINAE)
// -> std::enable_if_t<       
//     !std::is_rvalue_reference_v<decltype(a)> && 
//     !std::is_rvalue_reference_v<decltype(b)> &&
//     !std::is_rvalue_reference_v<decltype(c)>
//     , float>
{
    // type alias for common type
    using CommonType = std::common_type_t<decltype(a.data), decltype(b.data), decltype(c.data)>;

     X<CommonType> a_result(b.data - c.data);
     Y<CommonType> b_result(a.data - c.data);
     Z<CommonType> c_result(a.data + b.data);
    return static_cast<float>(a_result.foo(a.data) + b_result.foo(b.data) + c_result.foo(c.data));
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How can I pass these references to the same function?

How does having multiple shared references which value can be accessed just works in Rust?

How can i avoid circular references in type aliases

How can I find out which table a foreign key references?

How to avoid writing duplicate accessor functions for mutable and immutable references in Rust?

Does Elm allow circular references?

How can I separate these structs to avoid undefined behavior from multiple mutable references?

How can I search for all items which references match an input that can be multiple reference separated by a comma in excel?

How can I find which csv files are related (i.e., have foreign key references) to others?

How can I modify the DLL references of a program which I do not have the source code for?

How can I deal with DLL references in TFS?

How can I create a list of method references?

How can I have references of lists in Python

How can I enable references in WebAssembly with SpiderMonkey?

How can I deserialize a tree of references in Rust?

How can I share references in Word?

How can I share references across threads?

How can I initialize interdependent final references?

(How) Can I make a Dictionary for variable references?

How can I fill empty table rows which references another table's column ID?

Postgres: How Can I Make a JOIN/Junction Table Which References *One Of* Two Other Tables?

C# - How can I have an type that references any object which implements a set of Interfaces?

How can I manage python search paths or references in Visual Studio for Python files which are not part of a solution?

In Swift, how do I avoid both optionals and nil object references?

In NextJS, how can I avoid repeating the getStaticProps function on every page?

Function overwrites the same object every time: how can I avoid this?

How can a List<Long> references to an ArrayList which has BigInteger values

How will concepts lite interact with universal references?

how do I make a query which references other rows in a resultset?