【问题标题】:Restrict function parameters to certain enum values将函数参数限制为某些枚举值
【发布时间】:2017-06-30 10:38:05
【问题描述】:

这是我的第一次尝试-

#include <iostream>
using namespace std;

enum class props {
    left, right
};

template<typename T>
auto allowLeftOnly(T p) -> decltype((p==props::left), void())
{
    cout << "Wow!";
}

int main() {
    props p1 = props::left;
    props p2 = props::right;
    allowLeftOnly(p1);
    // allowLeftOnly(p2);  // should fail to compile
}

我对@9​​87654323@ 函数的要求是只接受props::left 或我明确指定为参数且无法为其他人编译的其他参数。这可能吗?

【问题讨论】:

  • 您必须将p 设为模板参数才能执行您想要执行的操作。
  • 您想用这个解决方案解决的实际问题是什么? 为什么你想这样做?请花一些时间阅读有关the XY problem 的信息,并思考您的问题如何成为它的一个例子。
  • @Someprogrammerdude 没有尝试解决任何实质性问题,而是尝试学习 c++ 的 TMP 方面

标签: c++ c++11 templates c++14 c++17


【解决方案1】:

不,这是不可能的。 p1p2 的值是运行时属性,而不是编译时属性,因此编译器在编译时并不“知道”它们的值。

您可以在编译时使用 constexpr 让它们知道,并将它们作为模板参数传递,例如:

#include <iostream>
#include <type_traits>

enum class props {
    left, right
};

template <props v>
typename std::enable_if<v == props::left, void>::type allowLeftOnly()
{ std::cout << "Wow!\n"; }

int main() {
    constexpr auto p1 = props::left;
    constexpr auto p2 = props::right;
    allowLeftOnly<p1>();
    allowLeftOnly<p2>(); // Fails to compile
}

【讨论】:

    【解决方案2】:

    您可以将p 更改为模板参数,然后使用std::enable_if,如下所示:

    template <props p> // p is now a template parameter
    std::enable_if_t<p == props::left> // We only allow p == props::left, return type is implicitly void
    allowLeftOnly() // No 'normal' parameters anymore
    {
        std::cout << "Wow!";
    }
    
    int main()
    {
        constexpr props p1 = props::left;
        constexpr props p2 = props::right;
        allowLeftOnly<p1>();
        // allowLeftOnly<p2>();  // Fails to compile
    }
    

    对于p1p2constexpr 关键字确保我们可以将变量用作模板参数。

    如果您稍后想要其他返回类型,例如 int,请使用:

    std::enable_if_t<p == props::left, int>
    

    【讨论】:

      【解决方案3】:

      由于其他答案建议使用模板参数,我还将添加一个答案,说明如何使用标记调度 (description from boost.org) 来实现这一点:

      #include <iostream>
      using namespace std;
      
      struct props
      {
          struct left {};
          struct right {};
      };
      
      void allowLeftOnly(props::left p)
      {
          cout << "Wow!";
      }
      
      int main()
      {
          allowLeftOnly(props::left{});
          // allowLeftOnly(props::right{});  // Fails to compile
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-28
        • 2017-03-30
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        相关资源
        最近更新 更多