提问者:小点点

std::is_reference来自std::any


我有点卡住了。

试图从模板类中检查参数是否是引用类型

它似乎在函数中起作用。

但在我的函数包装器中,它总是返回true。

#include <vector>
#include <any>

template <class T>
T CallFunction(const std::vector<std::any>& args) {
    for (size_t i = args.size(); i > 0; i--) {
        std::cout << std::boolalpha << std::is_reference<decltype(args[i-1].type())>::value << std::endl; // always true
    }
    return T();
}

template<typename Fn> class FunctionBase;
template<typename R, typename... Args>
class FunctionBase <R(__cdecl*)(Args...)> {
public:
    FunctionBase() {}
    R operator()(Args... args) {
        return CallFunction<R>({ args ... });
    }

};

int foo(int a, int& b) {
    std::cout << std::boolalpha << std::is_reference<decltype(a)>::value << std::endl; // falae
    std::cout << std::boolalpha << std::is_reference<decltype(b)>::value << std::endl; // true
    return a + b;
}

int main() {
    int in = 10;
    foo(1, in);

    FunctionBase<decltype(&foo)> func;
    func(1, in);
}

共2个答案

匿名用户

这里的前提是不正确的。 std::any始终拥有自己的值。 它将您给它的任何东西移动/复制到本地存储中,然后完全负责该独立实体:

int i = 1;
std::any a = i; // a owns an int whose value is 1, even though i is an lvalue here

i = 2;
assert(std::any_cast<int>(a) == 1); // still 1

std::any中存储“引用”的唯一方法是存储一个本身行为类似于引用的类型。。。 类似std::reference_wrapper:

int i = 1;
std::any a = std::ref(i); 

i = 2;
assert(std::any_cast<std::reference_wrapper<int>>(a).get() == 2);

但这实际上并不是一个引用,请注意,您不能使用any_cast-只能使用any_cast将其返回。

匿名用户

我认为您试图实现的是更像这样的东西:https://gcc.godbolt.org/z/-rq6jg

R operator()(args.。。args)中缺少一个通用引用,然后是CallFunction的完美转发,您希望将其声明为模板; CallFunction(arg&&&),然后通过在FunctionBase类中使用CallFunction(args))...实例化arg=intarg=int&;

#include <vector>
#include <any>
#include <iostream>

template <class T, class Arg>
T CallFunction(Arg&&) {
    std::cout << std::boolalpha << std::is_reference<Arg>::value << std::endl; // not always true
    return T();
}

template<typename Fn> class FunctionBase;
template<typename R, typename... Args>
class FunctionBase <R(*)(Args...)> {
public:
    FunctionBase() {}

    R operator()(Args&&... args) { // Args&& is a universal reference
        // Here we use perfect forwarding so that Args type does not change
        std::initializer_list<R>{CallFunction<R>(std::forward<Args>(args)) ...};
        return R();
    }
};

程序现在打印:

Program returned: 0

false

true

false

true