【问题标题】:c++ template meta programming: how do you define the type trait "is_xxxxx_v" alias for my custom trait?c ++模板元编程:如何为我的自定义特征定义类型特征“is_xxxxx_v”别名?
【发布时间】:2021-04-29 10:11:30
【问题描述】:

所以我一直在看这个:https://akrzemi1.wordpress.com/2017/12/02/your-own-type-predicate/

它表明您可以采用自定义特征(或谓词)is_thing<T>::type 并将其别名为 is_thing_t<T> - 例如:

template <bool Cond>
using enable_if_t = typename enable_if<Cond>::type;

现在我想用同样的技巧来实现其他特征中使用的值别名。我在下面尝试了一个 sn-p 代码:

// Primary template
// tparam 1 (T) is to pass in the class-under-test. 
// tparam 2 (deafult to void) is to catch all cases not specialised - so they evaluate to false
template <typename T, typename = void>
struct is_really_bob : std::false_type {};

// specialisation
// tparam 1 (T) is to pass in the class-under-test. 
// tparam 2 special meta-function that - if our class best-matches THIS template then it will evaluate to true
template <typename T>
struct is_really_bob <T, std::void_t<
    typename T::result_type,                 // Has a nested type called result_type
    decltype(T::check_bob()),                // Has a static member fn called check_bob
    decltype(std::is_default_constructible_v<T>), // required for below:
    decltype(T{}.set_bob(std::string{""})),  // has member fn set_bob that takes a string (also requires default c'tor)
    decltype(T{}.get_bob())                  // has member fn get_bob (also requires default c'tor)
>> : std::true_type {};

///// THIS FAILS /////
template <bool T>
using is_really_bob_v = typename is_really_bob<T>::value;

这里的问题是::value 不是类型名称。我不知道生成值别名的语法。有没有办法做到这一点?我希望最终能够做类似的事情:

if constexpr (is_really_bob_v<T>)
{
    // ...
}

完整的代码示例在这里:https://godbolt.org/z/dG11vxesW - 它没有将 ::value 别名的尝试注释掉,因此我们至少可以看到其余代码正常工作

【问题讨论】:

    标签: c++ templates template-meta-programming typetraits


    【解决方案1】:

    你对is_really_bob_v的定义有两个问题:

    1. 当模板需要类型时,您将其声明为 template &lt;bool T&gt;
    2. 您正在尝试使用类型别名来为布尔值设置别名。

    应该是

    template <typename T>
    //        ^^^^^^^^ not bool
    inline constexpr bool is_really_bob_v = is_really_bob<T>::value;
    //^^^^^^^^^^^^^^^^^^^no type alias     ^ no typename
    

    使用我的上述更正,以下工作按预期工作:

    struct BobTest {
      BobTest() = default;
      using result_type = bool;
    
      void set_bob(std::string) {}
    
      std::string get_bob() { return "bob"; }
    
      static void check_bob() {}
    };
    
    struct NonBobTest {
      NonBobTest() = default;
      // using result_type = bool;
    
      void set_bob(std::string) {}
    
      std::string get_bob() { return "bob"; }
    
      static void check_bob() {}
    };
    
    int main() {
      std::cout << "Is BobTest a real bob? " << is_really_bob_v<BobTest> << "\n";
      std::cout << "Is NonBobTest a real bob? "
                << is_really_bob_v<NonBobTest> << "\n";
    }
    

    输出:

    Is BobTest a real bob? 1
    Is NonBobTest a real bob? 0
    

    【讨论】:

    • 我不确定我在想什么 bool T!...大声笑,感谢您提供的额外细节 - 这会有所帮助
    【解决方案2】:

    从 C++14 开始,您可以将 variable template 声明为:

    template <typename T>
    inline constexpr bool is_really_bob_v = is_really_bob<T>::value;
    

    在 C++14 之前,您可以将其声明为类模板的静态数据成员,或作为 constexpr 函数模板的返回值。

    【讨论】:

    • 由于 OP 使用 std::void_t 我们可以假设 C++17。
    猜你喜欢
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多