简体   繁体   中英

overload variadic function with return type dependent on number of parameters

I am writing a multi-dimensional array class for which the number of dimensions is not known until runtime.

I have gotten to the subscript operator and would like to replicate the behavior of a multidimensional native array so that:

  • when using fewer subscripts than the number of dimensions, it will return an array (what might be called a "view")
  • when using a number of subscripts equal to the number of dimensions it will return the value stored at that location

Is it possible to have the return type depend on the relationship of the number of arguments passed to a function and a value that is not known until runtime (the number of dimensions)?

Other info:

  • I am implementing it as a sudo-multidimensional array by using a flat array and math to determine the correct index.
  • I am writing the subscript operator as a variadic function (non-templated).

The requirements,

  • when using ... it will return an array
  • when using ... it will return the value

contradict the standard (1.3.11) - a method or an operator cannot be overloaded on return types. So essentially it will be impossible for you to have something simple like:

class MyIndex; // defined elsewhere
template <typename T> struct MyArray {
   const std::array<T>& operator[] (const MyIndex& x) {...}
   const T&             operator[] (const MyIndex& x) {...}
   const T&             operator[] (int, int, int) {...}
};

As noted in the comments you could return a boost::variant or your own object instead. The variant is the better idea of course. The advantage of your own object is that you'll be able to control the conversions directly, but I don't consider this as a particularly good idea:

class Result; 
...
struct MyArrray {
   const Result& operator[] (const MyIndex& x) {...}
   const Result& operator[] (int, int, int) {...}

then add user defined conversions for Result or possibly separate getter operations to examine and retrieve values:

class Result {
    bool hasInt() const;
    operator int() const { /* throw if wraps a view else return the value */ }  
    bool hasView() const;
    operator MyArray() const { /* throw if wraps a value else return your array as a view */ }  

};

You can already note that this quickly becomes a quagmire. It'll be hard to maintain, hard to reason about, and your code will not be explicit to the readers or reviewers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM