C++ 如何在未赋值的上下文中获取应用于类成员的成员函数的结果类型

C++ 如何在未赋值的上下文中获取应用于类成员的成员函数的结果类型,c++,C++,我甚至不确定这个问题的标题是否正确。我想做的事情对我来说相当棘手,所以我甚至不知道如何用简洁的方式来描述它。很抱歉 我有一个值容器,它被包装在某种“安全”值类中。我需要一个函数,它接受指向该容器的指针,引用其成员之一,并发生以下情况: 如果传递的指针有效,函数将返回包装值内的值 如果传递的指针是nullptr,则函数返回默认构造值 总之,这里有一些代码 template<typename T> class Wrapped { T t; public: T& o

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

我有一个值容器,它被包装在某种“安全”值类中。我需要一个函数,它接受指向该容器的指针,引用其成员之一,并发生以下情况:

如果传递的指针有效,函数将返回包装值内的值

如果传递的指针是
nullptr
,则函数返回默认构造值

总之,这里有一些代码

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{}.
模板
类包装{
T;
公众:
T&运算符*(){
返回t;
}
};
类容器{
公众:
包裹我;
包皮;
};
//编译器错误与R。
//我希望R是由M表示的成员上调用运算符*的返回类型。
//我已经尝试了大约50种不同版本的声明来声明R的类型。这一种感觉最接近于我想要实现的目标。
//R应该是包装中的T。
模板
R值或默认值(T*对象,M成员,R默认值=R{})
{
对象?*(*对象)。*成员:默认值;
}
容器c;
auto-actual_int=value_或默认值(&c,&Container::i);//返回*(c.i)。
自动默认值_字符串=值_或_默认值(nullptr,&Container::s);//返回字符串{}。
那么:

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;
}
模板
类包装{
T{};
公众:
T&运算符*(){
返回t;
}
};
类容器{
公众:
包裹我;
包皮;
};
模板
R值\u或\u默认值(T*对象,包装的C::*成员)
{
返回*(*对象)。*成员);
}
模板
R值_或_默认值(nullptr_t,包装C::*,R默认值_值=R{})
{
返回默认值;
}
int main(){
容器c;
auto-actual_int=value_或_default(&c,&Container::i);//返回*(c.i)。
auto default_string=value_或_default(nullptr,&Container::s);//返回字符串{}。
std::cout怎么样:

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;
}
模板
类包装{
T{};
公众:
T&运算符*(){
返回t;
}
};
类容器{
公众:
包裹我;
包皮;
};
模板
R值\u或\u默认值(T*对象,包装的C::*成员)
{
返回*(*对象)。*成员);
}
模板
R值_或_默认值(nullptr_t,包装C::*,R默认值_值=R{})
{
返回默认值;
}
int main(){
容器c;
auto-actual_int=value_或_default(&c,&Container::i);//返回*(c.i)。
auto default_string=value_或_default(nullptr,&Container::s);//返回字符串{}。

我想你会写的

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

我想你会写

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

函数不能返回类型,但值除外。此外C++是强类型的,所以返回值的类型不能根据传递的函数参数来改变。@ÖöTiib我不知道你的意思。对我来说,这里有一个函数的返回类型基于传递的参数:
template T foo(T);
。您的示例中的foo不是函数,而是函数模板的声明,还有模板参数。@ÖTiib我已经重新表述了我认为是您有问题的句子。@ÖTiib我…不想争论这个问题。我希望您告诉我您不清楚我问题的哪一部分。函数不能返回类型但是除了C++之外,其他类型的返回值也不能根据所传递的函数参数来改变。可能是STD::变体可以帮助你(或者可能是它做你想要的)。;
。你的例子中的foo不是函数,而是函数模板的声明,还有模板参数。@ÖTiib我已经重新表述了我认为是你有问题的句子。@ÖTiib我…不想争论这个问题。我希望你告诉我你不清楚我问题的哪一部分。