带参数的流操纵器如何工作?

发布于 2024-12-12 05:58:02 字数 875 浏览 0 评论 0原文

在 Stroustrup 的 C++ 书中,有一个接受参数的自定义操纵器的示例(请参阅随附的代码)。我对结构是如何创建的感到困惑。特别是,“smanip”的构造函数似乎有两个 int 参数,一个用于函数指针“ff”,一个用于“ii”。我不明白如何传递 int 参数来创建结构:

cout << setprecision(4) << angle;

此外,这些函数的调用顺序是什么,以及类型参数 Ch 和 Tr 是如何确定的?多谢。

// manipulator taking arguments
struct smanip{
    iso_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

template<cladd Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

// usage:
cout << setprecision(4) << angle;

In Stroustrup's C++ book, there is an example of a custom manipulator taking an argument (pls see the attached code). I am confused about how the struct is created. In particular, it looks like there are two int arguments for the constructor of "smanip", one for the function pointer "ff", one for "ii". I don't understand how the int argument is passed to create the structure by using:

cout << setprecision(4) << angle;

In addition, what is the order these functions get called, and how the the type arguments Ch and Tr are determined? Thanks a lot.

// manipulator taking arguments
struct smanip{
    iso_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

template<cladd Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

// usage:
cout << setprecision(4) << angle;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

Saygoodbye 2024-12-19 05:58:02
setprecision(4)

调用

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

它从指向 set_ precision 函数的指针和 n 创建一个 smanip

struct smanip{
    ios_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

smanip 是一个结构体,包含一个指向函数的指针和一个整数。该函数通过引用获取 ios_baseint,并通过引用返回 ios_base

此时该行实际上是这样的:

smanip m(&setprecision, 4);
cout << m << (otherstuff);

与此模板匹配:

template<class Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

并且编译器可以从左侧的流中推导出 ChTr 。在本例中为 std::cout。该代码执行mf(os, mi)。这会调用 smanip 保存的函数指针,并向其传递流和 smanip 保存的整数。

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

这会调用cout.set precision(n)

所以该行翻译为:

std::cout.setprecision(4) << angle;
setprecision(4)

calls

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

Which creates an smanip from a pointer to the set_precision function, and n.

struct smanip{
    ios_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

smanip is a struct that holds a pointer to a function, and an integer. That function takes an ios_base by reference and an int, and returns the ios_base by reference.

At this point the line is effectively like this:

smanip m(&setprecision, 4);
cout << m << (otherstuff);

which matches this template:

template<class Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

And the compiler can deduce Ch, and Tr from the stream on the left side. In this case, std::cout. The code executes m.f(os, m.i). This calls the function pointer held by the smanip, passing it the stream and the integer held by smanip.

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

This calls cout.setprecision(n).

So the line translates to:

std::cout.setprecision(4) << angle;
层林尽染 2024-12-19 05:58:02

操纵器仿函数接受一个函数指针和一个 int 作为参数,并将两者存储在内部以供以后使用。为了便于阅读,构造函数的签名可以分为这两个声明:

typedef ios_base& (*f_ptr)(ios_base&,int);
smanip( f_ptr f, int )

也就是说,第一个参数是函数指针,第二个参数是值。

按照示例代码中的执行顺序,首先调用函数 set precision,该函数将函数指针和值存储在 smanip 对象中并返回它。该对象被传递给适当的运算符<<,该运算符在传递参数的当前流上提取并执行存储的函数指针。

// on the calling end
         setprecision(4)  // --> construct __s = smanip( set_precision, 4 )
(cout <<                ) // --> passes __s to `operator<<`
// inside operator<<
return m.f( os, m.i );    // calls: set_precision( os, 4 ) (m.f == &set_precision
                          //                                m.i == 4 )

The manipulator functor takes a function pointer and an int as arguments, and it stores both internally for later use. The signature of the constructor can be split in this two declarations for readability:

typedef ios_base& (*f_ptr)(ios_base&,int);
smanip( f_ptr f, int )

That is, the first argument is the function pointer and the second is the value.

As of the order of execution in the example code, first the function setprecision is called, that function stores the function pointer and value inside the smanip object and returns it. The object is passed to the appropriate operator<<, that extracts and executes the stored function pointer on the current stream passing the argument.

// on the calling end
         setprecision(4)  // --> construct __s = smanip( set_precision, 4 )
(cout <<                ) // --> passes __s to `operator<<`
// inside operator<<
return m.f( os, m.i );    // calls: set_precision( os, 4 ) (m.f == &set_precision
                          //                                m.i == 4 )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文