c++ 模板元编程:如何为我的自定义特征定义类型特征 "is_xxxxx_v" 别名?
c++ template meta programming: how do you define the type trait "is_xxxxx_v" alias for my custom trait?
所以我一直在看这个: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;
现在我想用同样的技巧来实现在其他特征中使用的值别名。我在下面尝试了一段代码:
// 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 别名的尝试,因此我们至少可以看到其余代码正常工作
你对is_really_bob_v
的定义有两个问题:
- 您将其声明为
template <bool T>
,而模板需要一个类型。
- 您正在尝试使用类型别名作为布尔值的别名。
应该是
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
从 C++14 开始,您可以将 variable template 声明为:
template <typename T>
inline constexpr bool is_really_bob_v = is_really_bob<T>::value;
在 C++14 之前,您可以将其声明为 class 模板的静态数据成员,或作为 constexpr 函数模板的 return 值。
所以我一直在看这个: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;
现在我想用同样的技巧来实现在其他特征中使用的值别名。我在下面尝试了一段代码:
// 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 别名的尝试,因此我们至少可以看到其余代码正常工作
你对is_really_bob_v
的定义有两个问题:
- 您将其声明为
template <bool T>
,而模板需要一个类型。 - 您正在尝试使用类型别名作为布尔值的别名。
应该是
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
从 C++14 开始,您可以将 variable template 声明为:
template <typename T>
inline constexpr bool is_really_bob_v = is_really_bob<T>::value;
在 C++14 之前,您可以将其声明为 class 模板的静态数据成员,或作为 constexpr 函数模板的 return 值。