Shadowing with 'using' declarations

I'm sure we've all be told about how using "using namespace ____" can be bad in a global scope. I had a question about the use of locally "using X = Y;" and whether it can cause problems later down the road.

When testing some code and changing features, I've been finding myself doing something like the following.
Each of these classes has different features, which I just represent for simplicity's sake as the print() member function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
struct Coordinate {
  double x;
  double y;
  double z;
  double w;
  void print() {std::cout << "Coordinate" << std::endl;}
};
struct Vector2 {
  double x; double y;
  void print() {std::cout << "Vec2" << std::endl;}
};
struct Vector3 {
  double x; double y; double z;
  void print() {std::cout << "Vec3" << std::endl;}
};

int main()
{
    using Coordinate = Vector2; // shadows the original Coordinate
    //using Coordinate = Coordinate; // works too!
    
    Coordinate c;
    c.print();
}


When doing this I realized that the using declarations in this way allows shadowing of types, seemingly without ambiguity.
If I want to change which implementation I want to use, I can easily just change the 1 line of "using" code to another.

I'm simply wondering if this could this cause problems for more complicated projects or do you agree that it's a good and efficient way for the coder to test and change to different implementations?
In what cases could this cause ambiguity, if any?
Last edited on
This is the kind of thing I would use typedef for, but I guess using is sort of the modern replacement (still not entirely sure why it's supposed to be better -- maybe it can be used for stuff other than types? Whatever).

Anyway, shadowing an existing typename is a terrible idea. If you already have a Coordinate struct, you should not redefine the name 'Coordinate' to be some other struct... at least not in the same namespace. If for no other reason than it leads to extremely confusing code.

Like... the #define int short level of confusing. Technically you can do it, but it's a terrible idea.

In your case, I would rename the Coordinate struct to Vector4, then there's no problem with using 'using' to define the typename 'Coordinate' to be one of those 3 vector structs.
Last edited on
I think this is a terribly bad practice. If you look at your code a month later, you'll first have to find out what each type actually means. It's much better to start out using clear, meaningful names for all your types.
Alright thanks for the input.
maybe it can be used for stuff other than types?
It can create templated type aliases.
http://coliru.stacked-crooked.com/a/1419cf014e7bcb76
I strongly advocate use of the using y = x; alias pattern - it lets you make shorter names for long things and saves typing. As long as you are responsible with naming there will not be any confusion. It is also cleaner-looking than typedef x y; and as MiiNiPaa shows it is required for templated aliases.
Last edited on
> you should not redefine the name 'Coordinate' to be some other struct...
> at least not in the same namespace.
it is not in the same namespace.


> It's much better to start out using clear, meaningful names for all your types.
Vector2 is a good name
Vector3 is a good name
Coordinate is a good name, and it may be more specific to the problem


> Each of these classes has different features
>> If I want to change which implementation I want to use, I can easily just change the 1 line of "using" code to another.
The classes don't have the same interface, they are not interchangeable.
1
2
template <class T>
using Container = std::vector<T>; //nih::vector<T> 


Also, I doubt that main would be the only function in that translation unit that needs to know what is a `Coordinate'.
Topic archived. No new replies allowed.