【问题标题】:Class template specialization with template template parameters具有模板模板参数的类模板特化
【发布时间】:2018-06-25 21:12:46
【问题描述】:

我正在尝试专门研究一个类型 s.t. 的类。它忽略了给定类型的常量。在这种情况下,类型是模板模板参数:

template <class T, typename Enable = void>
struct bar 
{
    bar()
    {
        static_assert(!std::is_same<T,T>::value, "no implementation of bar for type T");
    }
};

template <template <typename> class FooType, class T>
struct bar<FooType<T>, typename std::enable_if<std::is_same<typename std::remove_cv<FooType<T>>::type, foo<T>>::value>::type>
{};

上述代码在 GCC 4.8.4 和 clang 5.0(使用 -std=c++11)中都抱怨当与匹配 FooType 模板参数化的类一起使用时 bar 未定义。即使我去掉了sfinae参数,还是找不到特化。

可以在此处找到此问题的示例:https://godbolt.org/g/Cjci9C。 在上面的示例中,特化的构造函数有一个静态断言,当与 const FooType 一起使用时,即使 sfinae 参数被硬编码为 void 也是如此。当与非 const FooType 一起使用时,一切都按预期工作。

有人可以解释一下为什么 constness 在这种情况下禁止类型推断(匹配?)。

编辑(更新代码):

这是一个完全可编译的 sn-p。我试图在这个 sn-p 中捕获最小的例子。原始链接已更新以反映此示例。

#include <assert.h>
#include <type_traits>

template <class T>
struct foo {};

template <class T, typename Enable = void>
struct bar 
{
    bar()
    {
        static_assert(!std::is_same<T,T>::value, "no implementation of bar for type T");
    }
};

template <template <typename> class FooType, class T>
struct bar<FooType<T>, typename std::enable_if<std::is_same<typename std::remove_cv<FooType<T>>::type, foo<T>>::value>::type>
{};

int main()
{
  bar<foo<int>> mut_foo; // This is fine.
 // bar<const foo<int>> const_foo; // Error. No implementation found.
}

删除 main 第 2 行的注释会触发静态断言。我也试过 std::decay 和 std::remove_const 都没有成功。

编辑(非重复理由):

虽然链接的问题确实提出了类似的问题,但它不需要使用模板模板参数。它也只提供了一种解决问题的技术,并没有说明为什么给定的代码 sn-p 不起作用。有趣的是,该技术似乎不适用于模板模板参数,因为将以下 sn-p 替换为上述示例会导致相同的错误:

template <template <typename> class FooType, class T>
struct bar<FooType<T>,
           typename std::enable_if<std::is_same<FooType<T>, foo<T>>::value || std::is_same<FooType<T>, const foo<T>>::value>::type>
{};

【问题讨论】:

  • this 示例中,为bar&lt;const FooType&lt;T,U&gt;&gt; 添加新的特化匹配第二个示例。我想这些是规则,我不是 100% 确定。
  • 看起来this 是您的最小示例。
  • 我很难相信在没有任何#include 文件的情况下编译。
  • @JiveDadson 他没有发布整个代码,我猜你应该点击编译器资源管理器的链接
  • @Fransisco - 我想 mgoldman 应该发布一个最小的、完整的、可验证的示例。

标签: c++ c++11 templates


【解决方案1】:

const foo&lt;int&gt;FooType&lt;T&gt; 不匹配,
它将匹配 const FooType&lt;T&gt;T(或 const T)。

专业化匹配后,您可以添加 SFINAE:

所以,在你的情况下,你可以这样做

template <typename T> struct is_foo : std::false_type {};
template <typename T> struct is_foo<foo<T>> : std::true_type {};


template <class T>
struct bar<T,
           typename std::enable_if<is_foo<typename std::remove_cv<T>::type>::value>::type>
{};

【讨论】:

  • 如果我的理解是正确的,那么除了类型特征或依赖类型之外,没有办法推导出FooType的模板参数化?
  • 不确定我理解你的意思,但你可以实现is_same_template&lt;FooType, foo&gt;(但注意别名)和template_element&lt;I, FooType&lt;T&gt;&gt;::type(类似于tuple_element)或使用部分专业化,就像你尝试使用@ 987654330@,但你的方式不处理 cv_qualifiers。
  • 你能指出标准中关于这种类型的特殊化模式匹配的相关语言吗?
猜你喜欢
  • 2011-05-10
  • 2018-11-26
  • 2012-12-07
  • 2015-02-19
  • 2011-07-26
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多