Dot*_*one 3 c++ decltype type-traits c++-concepts c++20
我正在寻找一种方法来定义一个变量,该变量的类型取决于我的类模板化的类型的成员的类型,但需要注意的是该成员变量可能不存在。由于我仅在成员确实存在时访问块中的变量constexpr,因此我不关心声明它或它是什么类型。但是,我了解到这typename conditional<hasMember<T>, decltype(T::member), int>不起作用,因为未使用的分支仍然需要编译。
这是我希望开始工作的一个例子:
#include <iostream>
using namespace std;
struct X{};
struct Y{string member;};
template<class T>
concept hasMember = requires (T t) {t.member;};
template<class T>
struct A{
void hi(T a) {
// stuff
typename conditional<hasMember<T>, decltype(T::member), int /*member is unused if hasMember<T> is false, so I don't care what type it is or if it exists*/>::type member;
if constexpr (hasMember<T>){
member = a.member;
}
// stuff
if constexpr (hasMember<T>){
std::cout << member<< std::endl;
}
};
};
int main() {
X x;
Y y{"hi"};
// Does not compile
// A<X> ax;
// ax.hi(x);
// Compiles and runs fine
A<Y> ay;
ay.hi(y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
@TedLyngmo 的解决方案很可靠,并且还有更多替代方案。您可以简单地依赖编译器已经延迟实例化所有模板的事实,并定义一个类模板:
template <typename T>
struct member_type {
using type = decltype(T::member);
};
Run Code Online (Sandbox Code Playgroud)
只要您不访问::type,就不会member_type发生 的实例化。这可以被利用于std::conditional_t:
using M = std::conditional_t<hasMember<T>, member_type<T>, std::type_identity<int>>::type;
M member;
Run Code Online (Sandbox Code Playgroud)
您无需有条件地选择decltype(T::member)和int,而是选择包含这些类型的类模板::type。然后,::type仅访问所选的类模板,std::type_identity用作后备。