简体   繁体   English

我该如何解决该成员函数问题重载的地址?

[英]How can I resolve this address of overloaded member function issue?

[ EDIT - I long since forgot this was here until I got the 2,500 views "notable question". [ 编辑 -我很早就忘记了这里,直到我得到2500个视图的“显着问题”。 Since people are viewing - there is useful information about overloads in the accepted answer, but specifically checking for std::endl is even worse than I realized at the time, and definitely the wrong thing. 由于人们正在查看-在接受的答案中有关于重载的有用信息,但特别是检查std::endl情况甚至比我当时意识到的还要糟糕,这肯定是错误的事情。

Basically, the effect of std::endl is to output \\n to the stream then flush with std::flush . 基本上, std::endl的作用是将\\n输出到流中,然后使用std::flush That's irrespective of platform, including Windows where the end-of-line is really "\\r\\n". 这与平台无关,包括Windows,其行尾实际上是“ \\ r \\ n”。 The endl manipulator doesn't abstract away platform differences WRT line ends, C++ handles that the same way that C does - by translating \\n to "\\r\\n" (for text mode, not binary) later on. endl操纵器并没有抽象出WRT行末端的平台差异,C ++处理C的方式与之相同-稍后将\\n转换为“ \\ r \\ n”(对于文本模式,不是二进制)。 I thought C++ was doing something different, an assumption so strong I never even questioned it for 2 decades, but I was wrong. 我以为C ++会做一些不同的事情,这个假设是如此强烈,以至于20年来我从未质疑过它,但是我错了。

I don't remember details, but it's possible to define your own streams anyway, and provide alternative output (and translation) of whatever characters are streamed in. All manipulators should work as expected, before your custom stream code sees the resulting output characters. 我不记得详细信息,但是仍然可以定义自己的流,并提供流输入的任何字符的替代输出(和翻译)。 您的自定义流代码看到生成的输出字符之前 ,所有操纵器都应按预期工作。 So to provide special end-of-line behaviour, watch for the \\n there (which is still before the text-file end-of-line translation). 因此,要提供特殊的行尾行为,请注意其中的\\n (仍在文本文件行尾翻译之前)。 ] ]

It's hackish, I know, but I recently needed to implement a stream class which would act mostly like a standard stream, but which would detect the std::endl manipulator and special-case it's behaviour. 我知道这很棘手,但是最近我需要实现一个流类,该流类的行为基本上像是标准流,但是可以检测到std :: endl操纵器,并在特殊情况下可以检测其行为。 My first attempt at a particular method implementation was... 我对特定方法实现的首次尝试是...

mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
  if (p == &std::endl)
  {
    //  Handle special case
  }
  else
  {
    m_Underlying_Stream << p;
  }

  return *this;
}

The trouble with this is that the compiler doesn't know which overload of std::endl I'm referring to. 麻烦的是,编译器不知道我指的是std::endl重载。 I resolved it as follows... 我如下解决了...

mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
  typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);

  const ENDL_T l_ENDL (&std::endl);

  if (p == l_ENDL)
  {
    //  Handle special case
  }
  else
  {
    m_Underlying_Stream << p;
  }

  return *this;
}

That is the compiler can resolve the overload in the context of an initialisation (and for assignment too, as another experiment proved), but not for operator== . 也就是说,编译器可以在初始化的上下文中解决重载(并且也可以进行赋值,正如另一个实验证明的那样),但对于operator==不能。

The compiler in question is MinGW GCC 4.4.0, but I don't think this is likely to be a compiler issue. 有问题的编译器是MinGW GCC 4.4.0,但我认为这可能不是编译器问题。

I had a look around and found this question... 我环顾四周,发现了这个问题...

How to get the address of an overloaded member function? 如何获取重载成员函数的地址?

If my code has a const issue, I don't know where the missing const needs to go. 如果我的代码有一个const问题,我不知道丢失的const需要去哪里。 I can't see any other obvious type issue. 我看不到其他明显的类型问题。

I have some vague ideas about number-of-steps issues WRT overloading or implicit casting, but nothing concrete. 我对WRT重载或隐式转换的步数问题有一些模糊的想法,但是没有具体的想法。 So - can anyone explain clearly what is wrong with my first example, why the second version fixes it, and how I can safely indicate which overload I mean when taking the address of a function. 所以-任何人都可以清楚地说明我的第一个示例有什么问题,为什么第二个版本可以解决它,以及在使用函数地址时我如何可以安全地指出我的意思是哪个重载。

BTW - I can guess some people won't like me testing directly for the address of std::endl , and will point out that this is fragile - eg someone could have their own manipulator which calls std::endl which I wouldn't spot. 顺便说一句-我猜有些人可能不喜欢我直接测试std::endl的地址,并且会指出这很脆弱-例如某人可以拥有自己的操纵器,调用std::endl ,而我不会点。 In general this is true, but in this special case, the hack saves a lot of time and the nastiness just doesn't matter. 总的来说,这是对的,但是在这种特殊情况下,hack可以节省很多时间,而无关紧要。

The use of an overloaded function name, (or the name of a function template which behaves like a set of overloaded functions) without arguments (such as in an "address of" expression) is only allowed in a limited set of contexts where the context can be used to uniquely determine the particular overload required. 仅在有限的上下文集合中允许使用不带参数的重载函数名称(或行为类似于一组重载函数的函数模板的名称)(例如在“ address of”表达式中)可用于唯一确定所需的特定过载。

This is specified in 13.4 of the standard (ISO/IEC 14882:2003) [over.over]. 这是在标准(ISO / IEC 14882:2003)[over.over]的13.4中指定的。 Included are an initializer for an object or reference or in an explicit conversion. 包括用于对象或引用或显式转换的初始化器。 This gives you a number of options. 这给您许多选择。

Eg explicit conversion: 例如显式转换:

typedef std::ostream& (*ManipPtr)(std::ostream&);

mystream& mystream::operator<<(ManipPtr p)
{
    if (p == static_cast<ManipPtr>(&std::endl))
    {
        // ...

Directly initializing a pointer: 直接初始化指针:

typedef std::ostream& (*ManipPtr)(std::ostream&);

mystream& mystream::operator<<(ManipPtr p)
{
    const ManipPtr pEndl = &std::endl;

    if (p == pEndl)
    {
        // ...

The following works: 以下作品:

#include <iostream>

struct mystream {
    typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
    mystream& operator<< (ENDL_T p)
    {
        if (p == (ENDL_T)std::endl)
        {
            std::cout << "special case\n";
        }
        else
        {
            std::cout << "usual case\n";
        }
        return *this;
    }
};

int main()
{
    mystream ms;
    ms << std::endl; // prints "special case"
    ms << std::flush; // prints "usual case"
}

The reason it can't distinguish the overloads is because you're resolving the address of the function, not calling it. 它无法区分重载的原因是因为您正在解析函数的地址,而不是调用它。 When you insert it in the stream, the compiler knows to call the endl(ostream&) overload. 当您将其插入流中时,编译器就会知道调用endl(ostream&)重载。 Other than that, you're on your own. 除此之外,您是一个人。

Why not just test for '\\n' instead? 为什么不只测试'\\ n'呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获取重载成员function的地址? - How to get the address of an overloaded member function? 如何解决“找不到重载成员函数”错误? - How can I fix “Overloaded member function not found” error? 条件运算符无法解析重载的成员函数指针 - Conditional operator can't resolve overloaded member function pointers 语句无法解析重载函数的地址 - statement cannot resolve address of overloaded function 如何编写带有模板化函数参数的包装函数,该函数可以采用重载成员函数? - How do I write a wrapper function with templated function parameters which can take overloaded member functions? 如何在同一个类中调用另一个运算符重载成员函数的运算符重载成员函数(或使用运算符)? - How can i call a operator overloaded member function(or use the operator) from another operator overloading member function in the same class? 我只能使用const重载运算符成员函数吗? - Can I only have const overloaded operator member function? 我如何从其地址获取成员函数的组成部分? - How can i get constituents of a member function from its address? 如何获得COM对象的成员函数的地址? - How can I get the address of a COM object's member function? 如何使用cv-qualifier调用重载成员函数? - How do I call overloaded member function with cv-qualifier?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM