2

From here: Difference between 'struct' and 'typedef struct' in C++?, I found I need class identifier if there is name collision (for example if class name is the same as function name):

#include <iostream>

using namespace std;

class foo
{
public:
    foo() {}
    operator char const *() const
    {
        return "class";
    }
};

char const *foo()
{
    return "function\n";
}

int main()
{
    char const *p;
    p = class foo(); //this gets error
    cout << p << '\n';
    return 0;
}

output:

error: expected primary-expression before ‘class’
     p = class foo();

What is primary expression here and how can I identify the class instead of the function? I would like it to print class instead of function. How to do so?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • @ThomasSablik that's the point. You can, it is not good practise of course - but it is possible in C and as C++ is compatible with C, you can do as well. See the link I provided – milanHrabos Aug 15 '20 at 10:41
  • g++ seems to accept `typename ::foo()` to call the constructor, but clang does not. I guess this is not standard. – chi Aug 15 '20 at 15:14

3 Answers3

1

One of the possible solutions:

using bar = class foo;
p = bar();
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
0
int main()
{
    char const *p;
    struct foo f;
    p = static_cast<char const*>(f);
    cout << p << '\n';
    return 0;
}

By the way, the answer you link mentions that one can use typedef class foo foo; to trigger a compiler error for a function of same name. Havning a class and a function of same name isn't something desirable, but rather you need to workaround a bit the fact that the language allows it. And don't miss the last paragraph:

I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. The hiding rules in C were a mistake, and they should not have been extended to classes in C++. Indeed, you can correct the mistake, but it requires extra programming discipline and effort that should not be necessary.

If you are in control of either the function or the class you should definitely rename it or place it inside a namespace.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

I found two solutions that are accepted by both g++ and clang. I do not know, however, if they are standard C++.

  • Uniform initialization

     cout << (class foo){} << "\n";
    
  • Using a helper

    template <typename T, typename ...Args>
    T ctor(Args&& ...args) {
        return T{ std::forward<Args>(args) ... };
    }
    
    
    // ...
    
    cout << ctor<class foo>() << "\n";
    
chi
  • 111,837
  • 3
  • 133
  • 218