#include <iostream>
struct Foo {
template <int bias = 5>
void print() {
std::cout << bias << std::endl;
}
};
template <int bias = 5>
std::ostream &operator<<(std::ostream &os, const Foo &foo) {
return os << bias;
}
int main() {
Foo a;
a.print();
a.print<>();
a.print<1>();
std::cout << a << std::endl;
return 0;
}
通过显示这段代码,我的意思是,尽管实现很糟糕,但有没有办法将默认参数5
更改为使用std::cout << a << std::endl
格式输出Foo a
,并保持struct
不变?
是的,有一种方法可以显式调用运算符,这允许完整的模板实例化语法:
operator<<<3>(std::cout, a);
不过可读性不太好。为了恢复以前的行为(除了bias
的值(,您可以添加一个额外的
std::cout << 'n';
或者继续使用链接,请参阅Werner Henze的答案。
当您像运算符一样调用operator <<
时,不能添加模板参数。
std:cout << a << std::endl;
但是,如果像函数一样调用operator <<
,则可以添加模板参数。请注意,由于返回类型为std::ostream &
,您可以在运算符风格的语法中调用更多的operator <<
。
operator<< <3>(std::cout, a) << std::endl;
也可以在输出a
之前添加更多的operator <<
调用,但这一切看起来并不像原来的调用那么好。
operator<< <3>(std::cout << "a=", a) << std::endl;
另一个使用operator <<
的原始链接的选项通过引入一个helper类来工作。
template<int Bias>
struct Biased {
Biased(Foo& foo) :_foo{ foo } {}
Foo& _foo;
};
template<int Bias>
std::ostream& operator<<(std::ostream& os, const Biased<Bias>& biased) {
return os << Bias;
}
std::cout << "a=" << Biased<42>(a) << std::endl;
请注意,我在Biased
中添加了_foo
,这样Biased
的operator <<
也可以根据需要打印_foo
的内容(这在这里的代码中不会发生(。
在这种情况下,我更喜欢提供一个很好的工具来明确意图。
template<int bias>
struct Prefer
{
Prefer(Foo& foo) :foo{foo} {}
std::ostream &print(std::ostream &os) const {
return operator<< <bias>(os, foo);
}
private:
Foo& foo;
};
template <int bias>
std::ostream &operator<<(std::ostream &os, const Prefer<bias> &pref) {
return pref.print(os);
}
int main() {
Foo a;
a.print();
a.print<>();
a.print<1>();
std::cout << Prefer<2>(a) << std::endl;
std::cout << Prefer<10>(a) << std::endl;
return 0;
}
https://godbolt.org/z/j49Eo9