您可以为带有可变参数模板的类函数提供默认参数吗?

问题描述 投票:0回答:1

如果我想使用可变参数模板有一个默认参数,以下内容是完全有效的。我想知道类似的东西是否可以在班级中复制:

inline static constexpr auto myrun_func = [](auto b){std::cout<<b<<std::endl;};


template<class UnaryFunction, class... Args>
struct running_func{
    public:
        running_func(UnaryFunction&& unary, Args... args, const char* str = __builtin_FUNCTION()){
            std::cout<<"function was run from "<<str<<std::endl;
            std::forward<UnaryFunction>(unary)(args...);
        }
    
};

template<class UnaryFunction, class... Args>
running_func(UnaryFunction&& unary, Args... args) -> running_func<UnaryFunction, Args...>;

void test(){
    running_func(myrun_func, 10);
}

所以输出将是:

function was run from test()
10

我想知道我是否可以在这样的课堂上做类似的事情:

inline static constexpr auto myrun_func = [](auto b){std::cout<<b<<std::endl;};

class foo{
    template<class UnaryFunction, class... Args>
    struct running_func{
        running_func(foo* ex, UnaryFunction&& unary, Args... args, const char* str = __builtin_FUNCTION()){
            std::cout<<"function was run from "<<str<<std::endl;
            std::forward<UnaryFunction>(unary)(args...);
            ex->f();
        }
    };
    template<class UnaryFunction, class... Args>
    running_func(this, UnaryFunction&& unary, Args... args) -> running_func<UnaryFunction, Args...>;
    void f(){
        std::cout<<"f() called"<<std::endl; 
    }
};
void test(){
    foo example;
    example.running_func(myrun_func, 10);
}

以下显然行不通。但是,我想知道是否可以在

running_func
结构可以访问该类的地方使用类似的东西。

c++ c++17 variadic-templates variadic-functions
1个回答
0
投票

您的示例格式错误,您无法作为成员访问类型(尽管有建议),并且

this
不能在绑定函数上下文之外使用。如果您愿意稍微改变一下访问方法,您可以执行以下操作:

inline constexpr auto runnable = [](auto b) { std::cout << b << std::endl; };

/* `$' is a nonstandard identifier but I like how it looks :P */
template <typename...TT> struct $ : std::tuple<TT...> { };
template <typename...TT> $(TT&&...) -> $<TT...>;

struct Foo {
    void f() { std::cout << "f() called" << std::endl; }

    template <typename F, typename...TT>
    void running_func(F&& fn, $<TT...> tup, 
      const std::source_location& sl = std::source_location::current()) {
        std::cout << "function was run from `" << sl.function_name() << "'\n";
        std::apply(std::forward<F>(fn), static_cast<std::tuple<TT...>&>(tup));
        this->f();
    }
};

void test(){
    Foo foo {};
    foo.running_func(runnable, ${ 10 });
}

当然你也可以将其设为宏,但这会降低可读性:

inline constexpr auto runnable = [](auto b) { std::cout << b << std::endl; };

#define CALLER_FUNC your_name_here
#define running_func(...) CALLER_FUNC(std::source_location::current(), __VA_ARGS__)

struct Foo {
    void f() { std::cout << "f() called" << std::endl; }

    template <typename F, typename...TT>
    void CALLER_FUNC(const std::source_location& sl, F&& fn, TT&&...tt) {
        std::cout << "function was run from `" << sl.function_name() << "'\n";
        std::forward<F>(fn)(std::forward<TT>(tt)...);
        this->f();
    }
};

void test(){
    Foo foo {};
    foo.running_func(runnable, 10);
}
© www.soinside.com 2019 - 2024. All rights reserved.