我甚至不确定这个问题的标题是否正确。我试图做的事情对我来说相当粗糙,所以我甚至不知道如何以简洁的方式描述它。对不起。
我有一个价值观的容器,包含在某种安全的#34;价值等级。我需要一个函数来获取指向该容器的指针,对其成员之一的引用以及以下情况发生:
如果传递的指针有效,则该函数返回包装值内的值。
如果传递的指针是nullptr
,则该函数返回默认构造的值。
Anyhoo,这里有一些代码。
template<typename T>
class Wrapped {
T t;
public:
T& operator*() {
return t;
}
};
class Container {
public:
Wrapped<int> i;
Wrapped<string> s;
};
// Compiler error with R.
// I'd like R to be the return type of invoking operator* on the member that's represented by M.
// I've tried about 50 different versions of declarations to declare the type of R. This one feels like it most closely represents what I'm trying to achieve.
// R should be the T in Wrapped<T>.
template <typename T, typename M, typename R = decltype(declval<M>().operator*())>
R value_or_default(T* object, M member, R default_value = R{})
{
object ? *((*object).*member) : default_value;
}
Container c;
auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i).
auto default_string = value_or_default(nullptr, &Container::s); // Returns string{}.
答案 0 :(得分:2)
怎么样:
template<typename T>
class Wrapped {
T t{};
public:
T& operator*() {
return t;
}
};
class Container {
public:
Wrapped<int> i;
Wrapped<string> s;
};
template <typename T, typename R, typename C>
R value_or_default(T* object, Wrapped<R> C::* member)
{
return *((*object).*member);
}
template <typename R, typename C>
R value_or_default(nullptr_t, Wrapped<R> C::*, R default_value = R{})
{
return default_value;
}
int main() {
Container c;
auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i).
auto default_string = value_or_default(nullptr, &Container::s); // Returns string{}.
std::cout << actual_int << std::endl;
std::cout << default_string << std::endl;
return 0;
}
答案 1 :(得分:1)
我想你可以写
template <typename T, typename M,
typename R = typename std::remove_reference<
decltype(*(std::declval<M>()))>::type>
R value_or_default (T * o, M T::*m)
{ return o ? *(o->*m) : R{}; }
但你必须调用nullptr
案例来说明对象的类型(T
),因为编译器无法从nullptr
推断出它。
所以
Container c;
auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i).
auto default_string = value_or_default<Container>(nullptr, &Container::s);
// ....................................^^^^^^^^^
static_assert(std::is_same<int, decltype(actual_int)>::value, "!");
static_assert(std::is_same<std::string,
decltype(default_string)>::value, "!");