【问题标题】:How to conditionally instantiate a template class which has more than one template parameter?如何有条件地实例化具有多个模板参数的模板类?
【发布时间】:2019-09-21 17:46:18
【问题描述】:

我关注了这个帖子:Class template SFINAE 有条件地实例化模板类。

这对于只有一个模板参数的类非常有效,如上面的链接所示。

但是,我有两个(模板)参数,我想做一些 SFINE 检查。 以下是我的代码的最小示例。

#include <type_traits>
#include <string>

template<class T, class U, class R> using arithmetic_types =  std::enable_if_t<
    std::is_arithmetic_v<T> &&
    std::is_arithmetic_v<U>,
    R
>;

template<class T, class U, class Enable = void> class MyClass;
template<class T, class U, arithmetic_types<T, U, void>> 
class MyClass {
public:
    MyClass() = default;
};

int main()
{
    MyClass<int, int> o;          // should work
    MyClass<int, double> o1;      // should work
    MyClass<int, std::string> o2; // should be a complier error
    return 0;
}

上面给了我错误信息:https://godbolt.org/z/BEWJMp

error C3855: 'MyClass': template parameter 'Enable' is incompatible with the declaration
error C2079: 'o' uses undefined class 'MyClass'
error C2079: 'o1' uses undefined class 'MyClass'
error C2079: 'o2' uses undefined class 'MyClass'

很遗憾,我无法理解错误消息(error C3855:)。

为什么我不能按照上面链接中显示的相同原理来获得更多模板参数

什么是最好的解决方案

【问题讨论】:

  • @Wolf 我在 MSVC 16.0 中使用 C++17
  • @PiotrSkotnicki 除非你有可用的替代方案,否则不要使用 SFINAE 你能解释一下这个说法吗?有任何帖子吗?
  • SFINAE 基本上是迄今为止编译时性能最差的元编程技术。这不一定是您必须关心的事情,但对于大型项目(或模板库),这最终可能会成为争论的焦点。

标签: c++ class templates c++17 sfinae


【解决方案1】:

问题出在 MyClass 的模板特化中。特化应该只在TU这两个类上进行参数化,测试应该放在声明中,如下例所示。

#include <string>
#include <type_traits>

template <class T, class U, class R>
using arithmetic_types = std::enable_if_t<
    std::is_arithmetic_v<T> && std::is_arithmetic_v<U>, R>;

template <class T, class U, class Enable = void>
class MyClass;

template <class T, class U> //<- Remove the test from here
class MyClass<T, U, arithmetic_types<T, U, void>> //<- Put the test here.
{
public:
  MyClass() = default;
};

int main()
{
  MyClass<int, int> o;          // should work
  MyClass<int, double> o1;      // should work
  MyClass<int, std::string> o2; // should be a complier error
  return 0;
}

演示:https://godbolt.org/z/xTnwo9

【讨论】:

  • 很难看出(相信)差异。 +1 感谢 YSC
  • 不用悲观std::is_arithmetic_v。即使在 msvc 中也能正常工作。
  • @rustyx 抱歉,我在调查这类问题时使用的编译器只有一个 c++14 库。
  • @Johan 哦,是的......现在我看到了错误。感谢您的回答。
猜你喜欢
  • 2017-01-12
  • 1970-01-01
  • 2018-06-25
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 2012-12-26
相关资源
最近更新 更多