代码之家  ›  专栏  ›  技术社区  ›  shylent

从std::function[duplicate]的参数推断模板参数

  •  0
  • shylent  · 技术社区  · 7 年前

    template<class A>
    set<A> test(const set<A>& input) {
        return input;
    }
    

    我可以使用 test(mySet) 在代码中的其他位置,而不必显式定义模板类型。但是,当我使用以下功能时:

    template<class A>
    set<A> filter(const set<A>& input,function<bool(A)> compare) {
        set<A> ret;
        for(auto it = input.begin(); it != input.end(); it++) {
            if(compare(*it)) {
                ret.insert(*it);
            }
        }
        return ret;
    }
    

    当我使用 filter(mySet,[](int i) { return i%2==0; }); 我得到以下错误:

    然而,所有这些版本 工作:

    std::function<bool(int)> func = [](int i) { return i%2 ==0; };
    set<int> myNewSet = filter(mySet,func);
    
    set<int> myNewSet = filter<int>(mySet,[](int i) { return i%2==0; });
    
    set<int> myNewSet = filter(mySet,function<bool(int)>([](int i){return i%2==0;}));
    

    当我将lambda函数直接放在表达式中而不直接创建模板时,为什么c++11无法猜测模板类型 std::function ?

    编辑:

    template<class A,class CompareFunction>
    set<A> filter(const set<A>& input,CompareFunction compare) {
        set<A> ret;
        for(auto it = input.begin(); it != input.end(); it++) {
            if(compare(*it)) {
                ret.insert(*it);
            }
        }
        return ret;
    }
    

    这可以称为 set<int> result = filter(myIntSet,[](int i) { i % 2 == 0; }); 不需要模板。

    编译器甚至可以使用new decltype关键字和新函数return type语法在某种程度上猜测返回类型。以下示例使用一个过滤函数和一个基于值生成关键帧的函数将集合转换为贴图:

    template<class Value,class CompareType,class IndexType>
    auto filter(const set<Value>& input,CompareType compare,IndexType index) -> map<decltype(index(*(input.begin()))),Value> {
        map<decltype(index(*(input.begin()))),Value> ret;
        for(auto it = input.begin(); it != input.end(); it++) {
            if(compare(*it)) {
                ret[index(*it)] = *it;
            }
        }
        return ret;
    }
    

    map<string,int> s = filter(myIntSet,[](int i) { return i%2==0; },[](int i) { return toString(i); });
    
    0 回复  |  直到 7 年前
        1
  •  65
  •   David Rodríguez - dribeas    13 年前

    问题在于兰博达斯的性质。根据标准,它们是具有固定属性集的函数对象,但它们是 std::function<>

    但这并不意味着lambda就是一个 std::function 也不是函数指针。它们是独特的类型 operator() .

    另一方面,类型推断只会推断出精确的类型,而不进行转换(const/volatile限定除外)。因为lambda不是一个 std::函数 filter(mySet,[](int i) { return i%2==0; }); 无论如何 std::函数<&燃气轮机; 实例化。

    是相同类型的右值(临时)。

    int 对于模板,第二个工作示例,演绎不起作用。编译器将使用该类型,然后将lambda转换为适当的类型。

        2
  •  17
  •   Sarfaraz Nawaz    10 年前

    忘了你的案子吧。因为这对于分析来说太复杂了。

     template<typename T>
     struct X 
     {
         X(T data) {}
     };
    
     template<typename T>
     void f(X<T> x) {}
    

    现在打电话 f 作为:

     f(10); 
    

    T 将被推断为 int 因此,上述函数调用应该可以工作。事实并非如此。为了简单起见,想象一下 另一个 int

     template<typename T>
     struct X 
     {
         X(T data) {}
         X(int data) {} //another constructor
     };
    

    现在怎么办 T 当我写作时,应该推断为 f(10) ? 好 T 能够 任何 类型

    请注意,可能还有许多其他此类情况。以这种专业化为例:

     template<typename T>
     struct X<T*>         //specialized for pointers
     {
        X(int data) {}; 
     };
    

    现在怎么办 T 应该推断为该调用的 ? 现在看来更难了。

    std::function 兰博达斯 你不是那种人 std::函数 不同的 std::函数

        3
  •  3
  •   marianop    6 年前

    如果我们有:

    template <typename R, typename T>
    int myfunc(std::function<R(T)> lambda)
    {
      return lambda(2);
    }
    
    int r = myfunc([](int i) { return i + 1; });
    

    但如果您之前声明:

    template <typename Func, typename Arg1>
    static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> decltype((*func)(*arg1));
    
    template <typename Func>
    int myfunc(Func lambda)
    {
      return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);
    }
    

    这里有两段新代码。

    首先,我们有一个函数声明,它只对返回有用 参数:

    template <typename Func, typename Arg1>
    static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> decltype((*func)(*arg1)) {};
    

    template <typename Func>
    int myfunc(Func lambda)
    {
      return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);
    }
    

    有了正确的模板参数,现在我们可以调用真正的“myfunc”。 完整代码为:

    template <typename R, typename T>
    int myfunc(std::function<R(T)> lambda)
    {
      return lambda(2);
    }
    
    template <typename Func, typename Arg1>
    static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> decltype((*func)(*arg1)) {};
    
    template <typename Func>
    int myfunc(Func lambda)
    {
      return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);
    }
    
    int r = myfunc([](int i) { return i + 1; });
    

    可以为“getFuncType”声明任何重载以匹配lambda参数。例如:

    template <typename Func, typename Arg1, typename Arg2>
    static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr, Arg2* arg2 = nullptr) -> decltype((*func)(*arg1, *arg2)) {};