英文:
Resolve ambiguity
问题
我正在开发一个具有可变参数的方法,该方法起始于一个模板。
template<typename levelType, typename formatType, typename ... variadicParamsType>
void ClogLogger::log(levelType level, formatType format, variadicParamsType... formatParams)
{
string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << endl;
}
现在出现了错误:
log(0, "{}", "foo_1") // 打印 foo_1
log(0, "{} {}", "foo_1", "foo_2") // 错误,得到 <int, const char * e, const char * format, const char * formatParams>
另一方面,我有相同的方法,但还接受一个异常:
template<typename levelType, class exceptionType, typename formatType, typename ... variadicParamsType>
void log(levelType level, exceptionType e, formatType format, variadicParamsType ... formatParams)
{
string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << endl;
THROW_MYEXCEPTION(e.what());// 一个自定义宏
}
并且正常工作:
exception e;
log(0, e, "{}", "foo_1", "foo_2") // 现在正常工作
更新:
我似乎找到了问题,模板展开在以下情况下产生了歧义:
log(0, "{}{}" "foo_1", "foo_2")
这会展开为:
<int level, const char * e, const char * format, const char * formatParams>
这在调用 e.what()
时会导致错误。
您知道如何强制编译器使用第一个方法展开吗?即不包含异常的方法。
英文:
I am developing a method with variatic arguments that starts from a template.
template<typename levelType, typename formatType, typename ... variadicParamsType>
void ClogLogger::log(levelType level, formatType format, variadicParamsType... formatParams)
{
string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << endl;
}
Now the error:
log(0, "{}", "foo_1") // Prints foo_1
log(0, "{} {}", "foo_1", "foo_2") // Error, getting <int, const char * e, const char * format, const char * formatParams>
On the other hand I have this same method, but accepting also an exception:
template<typename levelType, class exceptionType, typename formatType, typename ... variadicParamsType>
void log(levelType level, exceptionType e, formatType format, variadicParamsType ... formatParams)
{
string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << endl;
THROW_MYEXCEPTION(e.what());// A custom macro
}
And performing well:
exception e;
log(0, e, {}{}, "foo_1", "foo_2") // Now, work´s fine
UPDATE:
I seem to have found the problem, the template expansion produces an ambiguity in the case:
log(0, "{}{}" "foo_1", "foo_2")
That expands as:
<int level, const char * e, const char * format, const char * formatParams>
This causes an error when e.what() is launched.
Do you know how I can force the compiler to expand using the first method? The one that does not contain the exception.
答案1
得分: 1
以下是翻译好的部分:
大致如下,也许:
template<typename levelType, class exceptionType, typename formatType,
typename ... variadicParamsType>
auto log(levelType level, const exceptionType& e, formatType format,
variadicParamsType... formatParams)
-> std::enable_if_t<(sizeof(decltype(e.what())*)>0)>
{
std::string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << std::endl;
THROW_MYEXCEPTION(e.what());// A custom macro
}
[演示](https://gcc.godbolt.org/z/3MW1sKhev)
这个想法是在重载决议中排除第二个重载,除非`e`“看起来像一个异常”,定义为“`e.what()`是一个良好形式的表达式”(因为函数的主体依赖于`e.what()`可用)。
请注意,代码中的注释和链接未翻译。如果需要更多帮助,请告诉我。
英文:
Something along these lines, perhaps:
template<typename levelType, class exceptionType, typename formatType,
typename ... variadicParamsType>
auto log(levelType level, const exceptionType& e, formatType format,
variadicParamsType... formatParams)
-> std::enable_if_t<(sizeof(decltype(e.what())*)>0)>
{
std::string levelHeader = getLevelHeader(level);
clog << levelHeader << fmt::format(format, formatParams...) << std::endl;
THROW_MYEXCEPTION(e.what());// A custom macro
}
The idea is to exclude the second overload from overload resolution unless e
"looks like an exception", defined as "e.what()
is a well-formed expression" (seeing as the body of the function relies on e.what()
being available).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论