我正在寻找一种方法来定义一个变量,其类型取决于我的类模板化的类型的成员类型,但需要注意的是该成员变量可能不存在。由于我仅在成员确实存在的情况下访问
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;
}
您可以创建一个老式类型特征来获取该类型:
template<class T, class O>
struct member_or {
static O test(...);
template<class U = T>
static auto test(int) -> decltype(U::member);
using type = decltype(test(0));
};
template<class T, class O>
using member_or_t = member_or<T, O>::type;
您的
A
实施可以是:
template <class T>
struct A {
void hi(T a) {
// stuff
member_or_t<T, int> member; // <- now no problem
if constexpr (hasMember<T>) {
member = a.member;
}
// stuff
if constexpr (hasMember<T>) {
std::cout << member << std::endl;
}
};
};