C++ 模板类的可变成员函数

C++ 模板类的可变成员函数,c++,templates,c++11,C++,Templates,C++11,我正面临一个问题,我正试图用特定类型的paramater包创建一个可变成员函数 template <typename T> struct A { using result_type = T; T operator()(T a, T b) { return a+b; } }; template <typename Functor> struct B { using T = typename Functor::

我正面临一个问题,我正试图用特定类型的paramater包创建一个可变成员函数

template <typename T>
struct A
{
    using result_type = T;

    T operator()(T a, T b)
    {
        return a+b;   
    }
};

template <typename Functor>
struct B
{
    using T = typename Functor::result_type;

    T operator()(Functor &&f, T... args)
    {
        return f(args...);
    }
};

实现预期功能的正确方法是什么?

您应该使用参数包。另外,为什么要尝试传递右值引用

template <typename Functor>
struct B
{
    using T = typename Functor::result_type;

    template<typename ...Args>
    T operator()(Functor f, Args... args)
    {
        return f(args...);
    }
};
模板
结构B
{
使用T=typename Functor::result\u type;
模板
T运算符()(函子f,Args…Args)
{
返回f(args…);
}
};
编辑:如果要验证所有参数是否为T类型,可以声明一个验证结构:

template <typename T, typename ...Pack>
struct verify_params {};

template <typename T>
struct verify_params<T> {
    using val=void;
};

template <typename T, typename ...Pack>
struct verify_params<T,T,Pack...> {
    using val=typename verify_params<T,Pack...>::val;
};
模板
结构验证参数{};
模板
结构验证参数{
使用val=void;
};
模板
结构验证参数{
使用val=typename验证参数::val;
};

然后,您可以添加一行,如
(typename verify_params::val)0到您的函数。

只有当函数是函数模板时,才能使用参数包

发件人:

模板参数包是接受零个或多个模板参数(非类型、类型或模板)的模板参数。函数参数包是接受零个或多个函数参数的函数参数

至少有一个参数包的模板称为可变模板

但是,您可以使用

int r = b(std::move(a), 2, 3);
做你的选择。保持参数类型不变,并使用
std::move(a)
或将函数更改为使用简单引用

 template <typename ... Args>
 T operator()(Functor& f, Args... args)
 {
     return f(args...);
 }
更新

您可以使用帮助器类来确保所有参数都是正确的类型

template<typename ... Args> struct IsSame : public std::false_type {};

template<typename T> struct IsSame<T> : public std::true_type {};

template<typename T, typename ... Args> struct IsSame<T, T, Args...> : public std::true_type
{
   static const bool value = IsSame<T, Args ...>::value;
};
失败了


我不知道在你的案例中是否需要对参数类型如此严格。如果需要,你有办法。

一个想法是使用
std::initializer\u list
,这将强制使用相同的类型(当然,你可能可以使用可变模板来解决这个问题,并巧妙地使用
std::is_same
为可变模板的所有参数强制使用相同的类型):


#include

可以实现一些SFINAE技巧,如:

struct Foo {};
template<class T, class...>
struct all_same : std::true_type
{};

template<class T, class U, class... SS>
struct all_same<T, U, SS...>
    : std::integral_constant<bool, std::is_same<T,U>{} && all_same<T, SS...>{}>
{};
structfoo{};
模板
结构全部相同:std::true\u类型
{};
模板
结构都一样
:std::积分常数
{};
那么

模板
结构B
{
使用T=typename Functor::result\u type;
模板
T运算符()(函子和函数,参数…参数)
{
静态断言(所有相同的{},“所有不相同的类型”);
返回f(args…);
}
};

演示

参数的类型不能是任何类型。它必须是typename Functor::result\u类型。我想传递一个通用转发引用以避免不必要的副本。对于第一个问题,您应该验证包中的元素(让我想想)。对于第二种方法,可以使用
std::move
,也可以使用const-lvalue引用。是否没有标准方法对参数类型应用限制,或者在参数包中使用特定类型?如果答案是否定的,那么我唯一能做的就是使用std::is_same进行静态_断言。
int r = b(std::move(a), 2, 3);
 template <typename ... Args>
 T operator()(Functor& f, Args... args)
 {
     return f(args...);
 }
 int r = b(a, 2, 3);
template<typename ... Args> struct IsSame : public std::false_type {};

template<typename T> struct IsSame<T> : public std::true_type {};

template<typename T, typename ... Args> struct IsSame<T, T, Args...> : public std::true_type
{
   static const bool value = IsSame<T, Args ...>::value;
};
template <typename ... Args>
T operator()(Functor&& f, Args... args)
{
   static_assert(IsSame<T, Args...>::value, "Invalid argument type");
   return f(args...);
}
A<int> a;
B<A<int>> b;
int r = b(std::move(a), 2, 3);
r = b(std::move(a), 2, 3.0);
#include <algorithm>
#include <initializer_list>
#include <utility>
#include <iostream>

template <typename T>
struct A
{
    using result_type = T;

    T operator()(std::initializer_list<result_type> const& li)
    {
        return std::accumulate(std::begin(li), std::end(li), 0.);
    }
};

template <typename Functor>
struct B
{
    using T = typename Functor::result_type;

    T operator()(Functor &&f, std::initializer_list<T> args)
    {
        return f(args);
    }
};

int main()
{
    A<int> functor;
    B<decltype(functor)> test;
    std::cout << test(std::move(functor), {1, 2, 3}); // displays 6
}
struct Foo {};
template<class T, class...>
struct all_same : std::true_type
{};

template<class T, class U, class... SS>
struct all_same<T, U, SS...>
    : std::integral_constant<bool, std::is_same<T,U>{} && all_same<T, SS...>{}>
{};
template <typename Functor>
struct B
{
    using T = typename Functor::result_type;

    template<typename ...Args>
    T operator()(Functor&& f, Args... args)
    {
        static_assert(all_same<T, Args...>{}, "all not same types");
        return f(args...);
    }
};