当前位置: 首页 > 知识库问答 >
问题:

是否有可能将SFINAE和模板专业化相结合?

缑智敏
2023-03-14
// the declaration
template<typename... Args>
struct ArgsEstimate;

// specialisation for string, SFINAE would be overkill
template<typename... Args>
struct ArgsEstimate<std::string&, Args...> {
    static const std::size_t size = 64 + ArgsEstimate<Args...>::size;
};

// specialisation for arithmetic types
template<typename AirthmeticT,
         typename std::enable_if<std::is_arithmetic<AirthmeticT>::value>::type* = nullptr,
         typename... Args>
struct ArgsEstimate<AirthmeticT, Args...> {
    static const std::size_t size = sizeof(AirthmeticT) + ArgsEstimate<Args...>::size;
};

// specialisation for pointer types
template<typename PtrT,
         typename std::enable_if<std::is_pointer<PtrT>::value>::type* = nullptr,
         typename... Args>
struct ArgsEstimate<PtrT, Args...> {
    static const std::size_t size = 32 + ArgsEstimate<Args...>::size;
};

我知道,我可能可以用SFINAE和函数重载单独做到这一点。但是,对于像std::string这样的情况,使用SFINAE是一种矫枉过正的做法。

所以我想知道是否有干净的方法来混合模板专业化和sfinae。

共有1个答案

全飞扬
2023-03-14

你可以,但你真的不能。不同的模板参数使情况变得复杂。

// specialisation for arithmetic types
template<class AirthmeticT, class... Args>
struct ArgsEstimate<
    AirthmeticT,
    std::enable_if_t<std::is_arithmetic_v<AirthmeticT>>,
    Args...>
{
    static const std::size_t size = sizeof(AirthmeticT) + ArgsEstimate<Args...>::size;
};

这管用...算是吧。您只需要确保第二个参数始终为void:

ArgsEstimate<int, void, /* ... */> ok; // will use the integer specialization

ArgsEstimate<int, int, int> wrong; // oups, will use the base template.

这不切实际。

// specialisation for arithmetic types
template<class T, class... Args>
    requires  std::is_arithmetic_v<T>
struct ArgsEstimate<T, Args...>
{
    static const std::size_t size = sizeof(T) + ArgsEstimate<Args...>::size;
};
template <class T, class Enable = void>
struct ArgEstimate {};

// specialisation for string, SFINAE would be overkill
template<>
struct ArgEstimate<std::string&>
{
    static const std::size_t size = 64;
};

// specialisation for arithmetic types
template<class T>
struct ArgEstimate<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
    static const std::size_t size = sizeof(T);
};

// specialisation for pointer types
template <class T>
struct ArgEstimate<T*>
{
    static const std::size_t size = 32;
};
// the declaration
template<class... Args> struct ArgsEstimate;

template<class T>
struct ArgsEstimate<T>
{
    static const std::size_t size = ArgEstimate<T>::size;
};

template<class Head, class... Tail>
struct ArgsEstimate<Head, Tail...>
{
    static const std::size_t size = ArgEstimate<Head>::size + ArgsEstimate<Tail...>::size;
};
template<class... Args>
struct ArgsEstimate
{
    static const std::size_t size = (... + ArgEstimate<Args>::size);
};
// specialisation for pointer types
template <class T, class... Args>
struct ArgsEstimate<T*, Args...> {
    static const std::size_t size = 32 + ArgsEstimate<Args...>::size;
};
 类似资料:
  • ii)当我更改代码并删除void_t时 0和0打印。表示,专门化是,所以我们使用基本模板。对于字符串,专门化无论如何都失败了。 我的问题:iii)有趣的部分。如果现在我把第一行改为使用int作为默认类型 有人能给我解释一下在iii)发生了什么吗?

  • 问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7

  • 对于将SFINAE与可变模板类一起使用,我似乎找不到一个好的解决方案。 假设我有一个不喜欢引用的可变参数模板对象: 以及一个类,可以方便地检查参数包是否包含引用: 我如何使用它来专门化NoRef的情况下,引用存在于arg包?

  • 看看这个简单的片段: clang编译了这个,但是gcc-7.2失败了: x、 cpp:5:20:错误:重新定义“struct Foo” 此错误消息似乎无效,在第5行,写入了。 哪个编译器是正确的?这是符合标准的代码吗?

  • 但是指定它是,因此它不再是模板类。它是否可以像虚函数一样专门化或重写?

  • 我有一个程序如下。有一个基本模板,以及SFINAE的部分专业化。 在2运行程序时,将打印 中的