奇怪的重复模板模式(CRTP)是正确的解决方案吗? 脚本 考虑一个类 Logger-,它具有标准C++类型重载的成员函数()(代码)>,并且也有一些方便的函数模板,如“代码>写”(代码>,内部调用()/代码>: 类记录器{ 公众: 无效写入(int x){…} 无效写入(双x){…} ... 模板 无效写线(tx){write(x);…} ... };
进一步考虑一个子类奇怪的重复模板模式(CRTP)是正确的解决方案吗? 脚本 考虑一个类 Logger-,它具有标准C++类型重载的成员函数()(代码)>,并且也有一些方便的函数模板,如“代码>写”(代码>,内部调用()/代码>: 类记录器{ 公众: 无效写入(int x){…} 无效写入(双x){…} ... 模板 无效写线(tx){write(x);…} ... };,c++,overloading,crtp,C++,Overloading,Crtp,进一步考虑一个子类dougoger,它为域特定类型添加了额外的write()重载(我们调用其中两个FooType1和FooType2): class傻瓜记录器:公共记录器{ 公众: 使用Logger::write; 无效写入(FooType1 x){…} 无效写入(FooType2 x){…} ... }; () 问题 直接调用时,现在支持两个类中任何一个提供重载的任何参数 但是,dougoger::writeLine()仅支持类记录器具有write()重载的参数类型。。。它没有看到在类dou
dougoger
,它为域特定类型添加了额外的write()
重载(我们调用其中两个FooType1
和FooType2
):
class傻瓜记录器:公共记录器{
公众:
使用Logger::write;
无效写入(FooType1 x){…}
无效写入(FooType2 x){…}
...
};
()
问题
直接调用时,现在支持两个类中任何一个提供重载的任何参数
但是,dougoger::writeLine()
仅支持类记录器
具有write()
重载的参数类型。。。它没有看到在类dougoger
中声明的附加write()
重载
我想让它看到它们,这样就可以用这些参数类型调用它了
当前解决方案
我使用奇怪的循环模板模式(CRTP)使其工作:
模板
类抽象记录器{
...
模板
void writeLine(tx){static_cast(this)->write(x);…}
};
类记录器:AbstractLogger{}
类傻瓜:公共抽象记录器{
...
};
()
虽然它完成了这项工作,但却以增加代码复杂性和烦躁为代价:
静态_cast
舞蹈!)AbstractLogger
和Logger
分为两类.cpp
文件),即使是那些不需要执行静态转换的函数
- CRTP是这项工作的正确工具吗
- 还有别的办法解决这个问题吗
操作符另一种方法如何:
template <typename ...Ts>
class Logger : private Ts...
{
public:
using Ts::write...;
void write(int x) { /*...*/ }
void write(double x) { /*...*/ }
// ...
template <typename T>
void writeLine(T x) { write(x); /*...*/ }
// ...
};
class FooWriter
{
public:
void write(FooType1 x) { /*...*/ }
void write(FooType2 x) { /*...*/ }
};
using FooLogger = Logger<FooWriter>;
模板
类记录器:专用Ts。。。
{
公众:
使用Ts::write。。。;
无效写入(int x){/*…*/}
空写(双x){/*…*/}
// ...
模板
无效写线(tx){write(x);/*…*/}
// ...
};
班级编剧
{
公众:
无效写入(FooType1 x){/*…*/}
无效写入(FooType2 x){/*…*/}
};
使用傻瓜记录器=记录器;
然后使用以下任一项(或其别名):
Logger
或Logger
或Logger
..顺便问一下,此模式是否有名称?请注意,PrintTo
的自由函数也可能导致ADL和ODR的细微错误。看见每种方法都有其优点和缺点。@Jarod42——事实证明,在我刷新了文档之后——对于GoogleTestPrintTo
来说,它不是一个免费函数,而是一个成员函数。但是,是的,作为一个自由函数可能会有问题。我自己会在一个特定的名称空间中使它成为一个免费函数,因为无论何时扩展任何名称空间(除了std
)都没有问题。你会发现这有什么问题吗?@Jarod42-同样在你的链接答案中(很好的一个BTW),我认为他遇到困难的代码不是因为打印是免费的-而是因为违反了ODR-不管怎样都可能发生。顺便说一句,在我们讨论这个问题时,有没有IDE诊断出这一点?(因为IDE通常有一个完整的程序视图,或者即使编译器没有,也至少有一个较宽的程序视图。)我的观点是,对于多个重载的自由函数,ODR冲突很容易发生,因为我们必须保证在不同的实例化点可以看到相同的重载。检测这一点很难:链接器可能会比较不同obj中的“相同”函数,看看它们是否真的相同,但对于内联代码,似乎为时已晚…@Jarod42-我想我的观点是,除了让OP的方法工作之外,他还要求OP提供其他方法,我认为这种方法具有优势-例如,重量较轻(IMO)。而且,我很少在实践中发现ODR问题(在其他人的代码中只有一到两次,尽管确实令人困惑),但是YMMV!