解决歧义

huangapple go评论71阅读模式
英文:

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&lt;typename levelType, typename formatType, typename ... variadicParamsType&gt; 
void ClogLogger::log(levelType level, formatType format, variadicParamsType... formatParams)
{
   string levelHeader = getLevelHeader(level);
   clog &lt;&lt; levelHeader &lt;&lt; fmt::format(format, formatParams...) &lt;&lt; endl;
}

Now the error:

log(0, &quot;{}&quot;, &quot;foo_1&quot;) // Prints foo_1 
log(0, &quot;{} {}&quot;, &quot;foo_1&quot;, &quot;foo_2&quot;) // Error, getting &lt;int, const char * e, const char * format, const char * formatParams&gt;

On the other hand I have this same method, but accepting also an exception:

template&lt;typename levelType, class exceptionType, typename formatType, typename ... variadicParamsType&gt; 
void log(levelType level, exceptionType e, formatType format, variadicParamsType ... formatParams)
{
   string levelHeader = getLevelHeader(level);
   clog &lt;&lt; levelHeader &lt;&lt; fmt::format(format, formatParams...) &lt;&lt; endl;
   THROW_MYEXCEPTION(e.what());// A custom macro
}

And performing well:

exception e;
log(0, e, {}{}, &quot;foo_1&quot;, &quot;foo_2&quot;) // Now, work&#180;s fine

UPDATE:

I seem to have found the problem, the template expansion produces an ambiguity in the case:

log(0, &quot;{}{}&quot; &quot;foo_1&quot;, &quot;foo_2&quot;) 

That expands as:

&lt;int level, const char * e, const char * format, const char * formatParams&gt;

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&lt;typename levelType, class exceptionType, typename formatType,
         typename ... variadicParamsType&gt; 
auto log(levelType level, const exceptionType&amp; e, formatType format,
         variadicParamsType... formatParams)
  -&gt; std::enable_if_t&lt;(sizeof(decltype(e.what())*)&gt;0)&gt;
{
    std::string levelHeader = getLevelHeader(level);
    clog &lt;&lt; levelHeader &lt;&lt; fmt::format(format, formatParams...) &lt;&lt; std::endl;
    THROW_MYEXCEPTION(e.what());// A custom macro
}

Demo

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).

huangapple
  • 本文由 发表于 2023年5月29日 22:17:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358105.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定