I guess this has been asked before, but I cannot find any answer to this
problem. I have program like this:
---SNIP---
#include <cassert>
#include <cstdlib>
class C
{
public:
inline operator float*() { return v; }
inline float& operator[](size_t i) { assert(i < 3); return v[i]; }
inline const float& operator[](size_t i) const
{ assert(i < 3); return v[i]; }
private:
float v[3];
};
int main()
{
C c;
c[1] = 0.0f;
return 0;
}
---SNIP---
Now, this does not compile, because the float* and the [] clash, since []
uses size_t (or unsigned) and the operator[] implicitly defined by the
float* conversion, also uses size_t, as far as I understand. Is there a way
to define both operators at the same time, while keeping the size_t of
operator[](size_t)?
Arne
--
[--- PGP key FD05BED7 --- http://www.root42.de/ ---] 6 2068
Arne Schmitz wrote: I guess this has been asked before, but I cannot find any answer to this problem. I have program like this:
---SNIP--- #include <cassert> #include <cstdlib>
class C { public:
inline operator float*() { return v; }
inline float& operator[](size_t i) { assert(i < 3); return v[i]; } inline const float& operator[](size_t i) const { assert(i < 3); return v[i]; }
private:
float v[3];
};
int main() { C c;
c[1] = 0.0f;
return 0; } ---SNIP---
Now, this does not compile, because the float* and the [] clash, since [] uses size_t (or unsigned) and the operator[] implicitly defined by the float* conversion, also uses size_t, as far as I understand. Is there a way to define both operators at the same time, while keeping the size_t of operator[](size_t)?
No, as you have discovered.
Drop the type conversion operator and use a normal, named, function:
float* get_v() { return v; }
V
Arne Schmitz wrote: I guess this has been asked before, but I cannot find any answer to this problem. I have program like this:
---SNIP--- #include <cassert> #include <cstdlib>
class C { public:
inline operator float*() { return v; }
inline float& operator[](size_t i) { assert(i < 3); return v[i]; } inline const float& operator[](size_t i) const { assert(i < 3); return v[i]; }
private:
float v[3];
};
int main() { C c;
c[1] = 0.0f;
return 0; } ---SNIP---
Now, this does not compile, because the float* and the [] clash, since [] uses size_t (or unsigned) and the operator[] implicitly defined by the float* conversion, also uses size_t, as far as I understand.
Not exactly. The built-in '[]' operator takes a _signed _ argument, namely - an
argument or 'ptrdiff_t' type.
The reason you have a clash in this case is that the 'c[1]' expression can be
interpreted in two different ways (as you correctly noted) and there's no clear
winner between the two.
Subscript operator has two parameters: "the pointer" and "the index".
The approach that uses the user defined conversion to 'float*' and the built-in
'[]' operator requires a user-defined conversion for the first argument and
requires no conversion for the second argument (or might require an integral
promotion 'int' -> 'ptrdiff_t').
The approach that uses the user-defined operator '[]' needs no conversion for
the first argument and requires an integral conversion ('int' -> 'size_t') for
the second argument.
According to the language specification neither approach is better than the
other one.
Is there a way to define both operators at the same time, while keeping the size_t of operator[](size_t)?
Probably no. Either change the parameter of the user defined '[]' operator to
have type 'ptrdiff_t'. Or remember to always explicitly use an unsigned value as
an index
c[1U] = 0.0f;
--
Best regards,
Andrey Tarasevich
Andrey Tarasevich wrote: ... Probably no. Either change the parameter of the user defined '[]' operator to have type 'ptrdiff_t'. Or remember to always explicitly use an unsigned value as an index
c[1U] = 0.0f; ...
.... although the latter is not guaranteed to resolve the ambiguity in general case.
--
Best regards,
Andrey Tarasevich
Andrey Tarasevich wrote: Is there a way to define both operators at the same time, while keeping the size_t of operator[](size_t)?
Probably no. Either change the parameter of the user defined '[]' operator to have type 'ptrdiff_t'. Or remember to always explicitly use an unsigned value as an index
c[1U] = 0.0f;
The first sounds good, but why e.g. does std::vector use size_t as the index
for operator[]? Are there any pros/cons?
The latter is too tedious for the programmer, I think. One can easily forget
the suffix U.
Arne
--
[--- PGP key FD05BED7 --- http://www.root42.de/ ---]
Arne Schmitz wrote: Andrey Tarasevich wrote:
Is there a way to define both operators at the same time, while keeping the size_t of operator[](size_t)?
Probably no. Either change the parameter of the user defined '[]' operator to have type 'ptrdiff_t'. Or remember to always explicitly use an unsigned value as an index
c[1U] = 0.0f;
The first sounds good, but why e.g. does std::vector use size_t as the index for operator[]? Are there any pros/cons?
'std::vector<>' uses 'std::vector<>::size_type' as an index (which, of course,
might be the same as 'std::size_t'). The 'std::vector's operator '[]' doesn't
need negative indexing and doesn't suffer form the ambiguity in question, which
makes it perfectly logical to choose an unsigned type for indexing.
Actually, I'd say that this applies to your situation as well. You don't need
negative indexing and therefore it makes more sense to stick with an unsigned
index type ('size_t' in your case). I wouldn't really recommend switching to a
signed type just to attempt to resolve the overloading ambiguity. In my previous
message I used the "workaround" with 'ptrdiff_t' just to illustrate how the
overload resolution works.
A more reasonable solution would be to get rid of the ambiguity by replacing the
'float*' conversion operator with a regular function (see Victor's message) or,
maybe, by removing it entirely. (Do you really need it?)
--
Best regards,
Andrey Tarasevich
Andrey Tarasevich wrote: 'std::vector<>' uses 'std::vector<>::size_type' as an index (which, of course, might be the same as 'std::size_t'). The 'std::vector's operator '[]' doesn't need negative indexing and doesn't suffer form the ambiguity in question, which makes it perfectly logical to choose an unsigned type for indexing.
Yes, makes sense.
Actually, I'd say that this applies to your situation as well. You don't need negative indexing and therefore it makes more sense to stick with an unsigned index type ('size_t' in your case). I wouldn't really recommend switching to a signed type just to attempt to resolve the overloading ambiguity. In my previous message I used the "workaround" with 'ptrdiff_t' just to illustrate how the overload resolution works.
True.
A more reasonable solution would be to get rid of the ambiguity by replacing the 'float*' conversion operator with a regular function (see Victor's message) or, maybe, by removing it entirely. (Do you really need it?)
No, I do not need it, although I bet quite a few programs here depend on the
'float*' operator. But they will have to adapt. :-)
Thank you for the very good explanations.
Arne
--
[--- PGP key FD05BED7 --- http://www.root42.de/ ---] This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Master of C++ |
last post by:
Hi,
This is a simple question. In the following example,
.. class Vector
.. {
.. private:
.. int *Numbers;
.. int vLength;
..
|
by: frs |
last post by:
See example below: Why does the output of 'a' work and the output of
'b' fails to compile? Is there a way to write class 'something' so that
'b' converts correctly by default? (include iostream,...
|
by: Clint Olsen |
last post by:
I just wrote some quick tests and my compiler (gcc) doesn't seem to flag
passing signed arguments to functions expecting unsigned types (and
presumably vice versa). Is there any particular reason...
|
by: Yuriy Solodkyy |
last post by:
Hi
VS 2005 beta 2 successfully compiles the following:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1 {
class Program {
|
by: Joe HM |
last post by:
Hello -
I have two Enums for which I would like to define type conversions ...
Public Enum eA
A2 = 0
A2 = 1
End Enum
Public Enum eB
B1 = 2
|
by: Dhirendra Singh |
last post by:
Hi,
The following C++ program is not compiling on my system.
#include <iostream>
using namespace std;
class complex {
double re, im;
public:
complex( ) :re(0), im(0) {}
|
by: Joseph Turian |
last post by:
I want to create several types of double, e.g. D1 and D2.
I want strong typing, such that a function defined for D1 will not
accept a D2 argument.
One solution is:
struct D1 {
double d;
};
...
|
by: zaeminkr |
last post by:
I got a good answer here I have still confusing part.
I have two very simple classes
class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) :...
|
by: Rahul |
last post by:
Hi Everyone,
I have the following code,
class B;
class A
{
public : operator B();
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |