如果可能的话,我想要一种一般的方法(如果它有.details,那么一个专业化,如果它有.other_info,那么一个不同的专业化,等等)。
如果我得到您的期望,您可以使用choice
-trick 组合,decltype
如下例所示:
#include <iostream>
template<int N>
struct choice: choice<N-1> {};
template<>
struct choice<0> {};
struct Foo { int error; };
struct Bar { int error; int details; };
struct Quux { int error; char other_info; };
template<typename MSG>
auto reportErr(choice<2>, const MSG& msg) -> decltype(msg.details, void()) {
std::cout << "ERROR: " << msg.error;
std::cout << ", details: " << msg.details << std::endl;
}
template<typename MSG>
auto reportErr(choice<1>, const MSG& msg) -> decltype(msg.other_info, void()) {
std::cout << "ERROR: " << msg.error;
std::cout << ", other_info: " << msg.other_info << std::endl;
}
template <typename MSG>
void reportErr(choice<0>, const MSG& msg) {
std::cout << "ERROR: " << msg.error << std::endl;
}
template <typename MSG>
void reportErr(const MSG &msg) {
reportErr(choice<100>{}, msg);
}
int main() {
reportErr(Foo{0});
reportErr(Bar{0, 42});
reportErr(Quux{0, 'c'});
}
查看它并运行wandbox
(实际上使用 GCC 4.5.4,您提到的版本不可用)。它利用重载解析根据消息的类型选择函数的工作版本,并丢弃介于两者之间的所有内容。您可以添加更多的特化(让我们这样称呼它们,即使它们毕竟不是正确的特化)并通过根据需要调整参数来根据您的偏好对它们进行排序(choice
其值越高,特化的优先级越高)。
类似的事情也可以通过将choice
-trick 与sizeof
基于 SFINAE 的解决方案相结合来完成,类似于我上面显示的。
特别是,这是一个工作示例:
#include <iostream>
template<int N>
struct choice: choice<N-1> {};
template<>
struct choice<0> {};
struct Foo { int error; };
struct Bar { int error; int details; };
struct Quux { int error; char other_info; };
template<typename MSG, std::size_t = sizeof(MSG::details)>
void reportErr(choice<2>, const MSG& msg) {
std::cout << "ERROR: " << msg.error;
std::cout << ", details: " << msg.details << std::endl;
}
template<typename MSG, std::size_t = sizeof(MSG::other_info)>
void reportErr(choice<1>, const MSG& msg) {
std::cout << "ERROR: " << msg.error;
std::cout << ", other_info: " << msg.other_info << std::endl;
}
template <typename MSG>
void reportErr(choice<0>, const MSG& msg) {
std::cout << "ERROR: " << msg.error << std::endl;
}
template <typename MSG>
void reportErr(const MSG &msg) {
reportErr(choice<100>{}, msg);
}
int main() {
reportErr(Foo{0});
reportErr(Bar{0, 42});
reportErr(Quux{0, 'c'});
}
查看它并在 上运行wandbox
。优点是该解决方案不会受到您在前一个解决方案中收到的烦人警告的影响。
我使用比您要求的更旧的编译器(GCC 4.5.4)对其进行了测试,因此我非常有信心它们都可以与 GCC 4.6.x 一起使用。