如何解决在使用constexpr方法时出现“函数模板已经被定义”错误的问题。

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

How to work around "function template has already been defined" when using std::enable_if with constexpr method

问题

当在std::enable_if_t的参数中使用constexpr方法时,旧版MSVC编译器会报告“函数模板已经定义”的错误。G++和较新版本的MSVC编译器会接受此代码。如何使旧版MSVC编译器也能正常工作?

示例代码:

#include <climits>
#include <iostream>
#include <type_traits>

template <typename NumberType>
constexpr auto doBitCountsMatch(const int f_bitCount) -> bool {
  return (static_cast<int>(CHAR_BIT * sizeof(NumberType)) == f_bitCount);
}

template <typename NumberType, int bitCount>
auto test() -> std::enable_if_t<doBitCountsMatch<NumberType>(bitCount), NumberType> {
  std::cout << "Bit counts match." << std::endl;
  return 0;
}

template <typename NumberType, int bitCount>
auto test() -> std::enable_if_t<!doBitCountsMatch<NumberType>(bitCount), NumberType> {
  std::cout << "Bit counts don't match." << std::endl;
  return 0;
}

int main() {
  int number = 0;
  test<decltype(number), 32>();
  return 0;
}

在Compiler Explorer上查看:https://godbolt.org/z/15PnPhvo8。MSVC 19.14拒绝此代码,MSVC 19.33接受它。为什么旧版编译器拒绝该代码?

英文:

When using a constexpr method as the argument of std::enable_if_t, old MSVC compilers complain about "function template has already been defined". G++ and newer MSVC compilers accept that. How I can make that work also with old MSCV compilers?

Example code:

#include &lt;climits&gt;
#include &lt;iostream&gt;
#include &lt;type_traits&gt;

template &lt;typename NumberType&gt;
constexpr auto doBitCountsMatch(const int f_bitCount) -&gt; bool {

  return (static_cast&lt;int&gt;(CHAR_BIT * sizeof(NumberType)) == f_bitCount);
}

template &lt;typename NumberType, int bitCount&gt;
auto test()
    -&gt; std::enable_if_t&lt;doBitCountsMatch&lt;NumberType&gt;(bitCount), NumberType&gt; {
  std::cout &lt;&lt; &quot;Bit counts match.&quot; &lt;&lt; std::endl;

  return 0;
}

template &lt;typename NumberType, int bitCount&gt;
auto test()
    -&gt; std::enable_if_t&lt;!doBitCountsMatch&lt;NumberType&gt;(bitCount), NumberType&gt; {
  std::cout &lt;&lt; &quot;Bit counts don&#39;t match.&quot; &lt;&lt; std::endl;

  return 0;
}

int main() {
  int number = 0;

  test&lt;decltype(number), 32&gt;();
  return 0;
}

And here in Compiler Explorer: https://godbolt.org/z/15PnPhvo8: MSVC 19.14 rejects the code, MSVC 19.33 accepts it. Why do the old compilers reject the code?

答案1

得分: 2

你可以使用 std::enable_if_t 作为模板参数代替:

template <typename NumberType, int bitCount,
          std::enable_if_t<doBitCountsMatch<NumberType>(bitCount), int> = 0>
auto test() -> NumberType
{
  std::cout << "Bit counts match." << std::endl;

  return 0;
}

template <typename NumberType, int bitCount,
          std::enable_if_t<!doBitCountsMatch<NumberType>(bitCount), int> = 0>
auto test() -> NumberType
{
  std::cout << "Bit counts don't match." << std::endl;

  return 0;
}

演示

英文:

You might use std::enable_if_t as template parameter instead:

template &lt;typename NumberType, int bitCount,
          std::enable_if_t&lt;doBitCountsMatch&lt;NumberType&gt;(bitCount), int&gt; = 0&gt;
auto test() -&gt; NumberType
{
  std::cout &lt;&lt; &quot;Bit counts match.&quot; &lt;&lt; std::endl;

  return 0;
}

template &lt;typename NumberType, int bitCount,
          std::enable_if_t&lt;!doBitCountsMatch&lt;NumberType&gt;(bitCount), int&gt; = 0&gt;
auto test() -&gt; NumberType
{
  std::cout &lt;&lt; &quot;Bit counts don&#39;t match.&quot; &lt;&lt; std::endl;

  return 0;
}

Demo

huangapple
  • 本文由 发表于 2023年3月9日 23:24:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686697.html
匿名

发表评论

匿名网友

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

确定