【问题标题】:Using enable_if with struct specialization将 enable_if 与结构特化一起使用
【发布时间】:2017-03-08 17:46:08
【问题描述】:

我正在尝试定义一个模板,它将在给定另一种类型 T 的情况下指定存储类型。我想使用 enable_if 来捕获所有算术类型。下面是我对此的尝试,它抱怨模板是用 2 个参数重新声明的。我尝试向主模板添加第二个虚拟参数,但得到不同的错误。如何做到这一点?

#include <string>
#include <type_traits>
template <typename T> struct storage_type; // want compile error if no match
// template <typename T, typename T2=void> struct storage_type; // no joy
template <> struct storage_type<const char *> { typedef std::string type; };
template <> struct storage_type<std::string> { typedef std::string type; };
template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr> 
    struct storage_type { typedef double type; };

// Use the storage_type template to allocate storage
template<typename T>
class MyStorage {
  public:
  typename storage_type<T>::type storage;
};

MyStorage<std::string> s;  // uses std::string
MyStorage<const char *> s2; // uses std::string
MyStorage<float> f;  // uses 'double'

【问题讨论】:

  • 请注意long double 可以大于doublelong long 也至少为 64 位,但可能更大。
  • 先修复obvious stuff
  • @πάνταῥεῖ 我相信这就是他要问的,如何解决这个错误。
  • @JustinTime 从长远来看没有多大帮助。
  • 我的实际用法有些不同,所以我通过输入一个简单的双精度类型来简化问题以提出问题。不用担心,我不想将较大的类型塞入较小的分配中。感谢您的敏锐眼睛,因为这可能非常重要,并且可能会节省其他人阅读本文的时间。

标签: c++ templates enable-if


【解决方案1】:

您可以通过向主模板添加第二个参数,然后专门匹配它来做到这一点;你在正确的轨道上,但没有正确地做。

#include <string>
#include <type_traits>
// template <typename T> struct storage_type;                // Don't use this one.
template <typename T, typename T2=void> struct storage_type; // Use this one instead.
template <> struct storage_type<const char *> { typedef std::string type; };
template <> struct storage_type<std::string> { typedef std::string type; };

// This is a partial specialisation, not a separate template.
template <typename T> 
struct storage_type<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
    typedef double type;
};

// Use the storage_type template to allocate storage
template<typename T>
class MyStorage {
  public:
  typename storage_type<T>::type storage;
};

MyStorage<std::string> s;  // uses std::string
MyStorage<const char *> s2; // uses std::string
MyStorage<float> f;  // uses 'double'

// -----

struct S {};

//MyStorage<S> breaker; // Error if uncommented.

And voila.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多