如何在未评估的上下文中将成员函数的结果类型应用于类成员



我什至不确定这个问题的标题是否正确。我想做的事对我来说是相当粗糙的,所以我什至不知道如何以简洁的方式描述它。抱歉。

我的值容器包裹在某种"安全"价值类中。我需要一个将指针指向该容器的函数,引用其成员之一,以下发生了:

如果指针传递是有效的,则该函数将返回包装值内部的值。

如果指针传递为 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{}.

怎么样:

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;
}

我想你可以写

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推导。

so

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, "!"); 

相关内容

最新更新