【问题标题】:Template specialization based on integer constant comparison基于整数常量比较的模板特化
【发布时间】:2019-03-11 00:47:28
【问题描述】:

这是我有的东西:

template <typename T, std::size_t dim>
struct vector;

template <std::size_t dim>
struct vector<float, dim>
{
    // I want this implementation for dim <= 4
}

template <std::size_t dim>
struct vector<float, dim>
{
    // I want this implementation for dim > 4
}

int main() {
    vector<float, 3> v1; // should instantiate first one
    vector<float, 7> v2; // should instantiate second one
}

现在,这当然不是一个有效的例子,因为我无法让它工作。我不知道如何安排专业化模板签名。它们现在是相同的模板参数,不会编译。不知何故,我猜应该有一种 SFINAE 进入图片,但我不允许在部分专业化上使用默认模板参数。

我可以使用constexpr if 来处理代码选择并改为使用一种专业化。但我相信,对这些进行单独的专业化会使事情更具可读性和可管理性。

您将如何实现这一目标?

【问题讨论】:

    标签: c++ templates sfinae


    【解决方案1】:

    您可以使用 SFINAE 实现此目的。你向非特化模板添加一个额外的模板参数,然后确保在你的特化中匹配它以适应特定条件。

    template <typename T, std::size_t dim, typename = void>
    struct vector;
    
    template <std::size_t dim>
    struct vector<float, dim, std::enable_if_t<(dim <= 4)>>
    {
        // I want this implementation for dim <= 4
    };
    
    template <std::size_t dim>
    struct vector<float, dim, std::enable_if_t<(dim > 4)>>
    {
        // I want this implementation for dim > 4
    };
    
    int main() {
        vector<float, 3> v1; // should instantiate first one
        vector<float, 7> v2; // should instantiate second one
    }
    

    std::enable_if_t 如果传递给它的条件为真,默认情况下会推断为void。如果不是,它不会推断出任何导致替换失败的内容,从而为任何其他模板匹配。

    std::enable_if_t 需要c++14,但您可以使用typename std::enable_if&lt;condition&gt;::type,因为c++11

    【讨论】:

    • 在第一行,你的意思是typename = void,而不是template = void
    • 准确地说,std::enable_if_t 从 C++14 开始可用。
    【解决方案2】:

    使用附加层的可能解决方案。我们为此 arg 使用额外的 bool 模板参数和特化。可用于С++11以下的版本。

    template <typename T, std::size_t dim, bool moreThanFour>
    struct vectorImpl;
    
    template <std::size_t dim>
    struct vectorImpl<float, dim, false>
    {
       // I want this implementation for dim <= 4
    };
    
    template <std::size_t dim>
    struct vectorImpl<float, dim, true>
    {
       // I want this implementation for dim > 4
    };
    
    template <typename T, std::size_t dim>
    struct vector : public vectorImpl < T, dim, (dim > 4) > {};
    
    int main() {
       vector<float, 3> v1; // should instantiate first one
       vector<float, 7> v2; // should instantiate second one
    }
    

    【讨论】:

      【解决方案3】:

      有了概念,你可以简单地写:

      template <typename T, std::size_t dim>
      struct vector;
      
      template <std::size_t dim>
          requires (dim <= 4)
      struct vector<float, dim>
      {
          // I want this implementation for dim <= 4
      };
      
      template <std::size_t dim>
          requires (dim > 4)
      struct vector<float, dim>
      {
          // I want this implementation for dim > 4
      };
      

      查看godbolt

      我们只需要等待他们

      【讨论】:

      • 等不及 C++ 20 :P
      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多