【问题标题】:SFINAE with variadic template classes?带有可变参数模板类的 SFINAE?
【发布时间】:2012-12-19 09:09:25
【问题描述】:

我似乎找不到将 SFINAE 与可变参数模板类一起使用的好解决方案。

假设我有一个不喜欢引用的可变参数模板对象:

template<typename... Args>
class NoRef
{
    //if any of Args... is a reference, this class will break
    //for example:
    std::tuple<std::unique_ptr<Args>...> uptrs;
};

还有一个类可以方便地检查参数包是否包含引用:

template<typename T, typename... Other>
struct RefCheck
{
    static const bool value = std::is_reference<T>::value || RefCheck<Other...>::value;
};
template<typename T>
struct RefCheck<T>
{
    static const bool value = std::is_reference<T>::value;
};

对于 arg 包中存在引用的情况,我如何使用它来专门化 NoRef?

【问题讨论】:

    标签: c++ variadic-templates sfinae


    【解决方案1】:

    这不使用 SFINAE,但本质上是你想要的:

    template<bool Ref, typename... Args>
    class NoRef_;
    
    template<typename... Args>
    class NoRef_<false, Args...>
    {
        std::tuple<std::unique_ptr<Args>...> uptrs;
    };
    template<typename... Args>
    class NoRef_<true, Args...>
    {
        // contains reference
    };
    
    template<typename... Args>
    using NoRef = NoRef_<RefCheck<Args...>::value, Args...>;
    
    // alternative from Nawaz
    
    template<typename... Args> struct NoRef : NoRef_<RefCheck<Args...>::value, Args...> {}
    

    【讨论】:

    • +1。但我认为template&lt;typename... Args&gt; struct NoRef : NoRef_&lt;RefCheck&lt;Args...&gt;::value, Args...&gt; {}; 会更好。现在NoRef 是一个不同的类模板,没有非类型模板参数(即布尔值)。
    • 我喜欢这个解决方案,尽管我还不能在 MSVC 中为模板设置别名。但 Nawaz 也提供了解决方案。
    【解决方案2】:

    恐怕这是不可能的,因为模板包很笨重。但是,您可以打包。

    // Used to transport a full pack in a single template argument
    template <typename... Args> struct Pack {};
    

    我们调整参考检查:

    template <typename T, typename... Other>
    struct RefCheck
    {
        static const bool value = std::is_reference<T>::value
                               || RefCheck<Other...>::value;
    };
    
    template <typename T>
    struct RefCheck<T>
    {
        static const bool value = std::is_reference<T>::value;
    };
    
    template <typename... Args>
    struct RefCheck<Pack<Args...>>: RefCheck<Args...> {};
    

    现在我们可以使用Pack

    template <typename P, bool = RefCheck<P>::value> class NoRef;
    
    template <typename... Args>
    class NoRef<Pack<Args...>, false> {
        // no reference in Args... here
    };
    

    【讨论】:

      猜你喜欢
      • 2015-12-14
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      相关资源
      最近更新 更多