【问题标题】:How to use class template argument to change argument calls and function signatures?如何使用类模板参数来更改参数调用和函数签名?
【发布时间】:2020-05-24 18:02:32
【问题描述】:

我正在尝试找到设计类模板的方法,以便传递 int 值,并且几个函数签名以及参数列表都依赖于该值。

特别是考虑到MyClass

template <int N>
class MyClass {
    typedef SomeType<int, int, int, /* ... N times*/ > MyDepType;
    myFunction(std::string arg0, std::string  arg1, /* ...*/ std::string  argN) { /* do stuff */};
 public:
    MyClass() {
        someFunction(float arg0, float arg1, /* ...*/ float argN);   // <
        someOtherFunction(boost::bind(&MyClass::myFunction, this, _1, _2, /*...*/ _N));
    };
};

我希望能够表达私有 typedef 调用、myFunction 的签名和传递给外部函数 someFunctionsomeOtherFunction 的参数列表,我无法编辑/重写。 有没有办法使用 C++11 标准来实现这一点?

【问题讨论】:

  • 为什么不使用parameter pack
  • 或者 std::array?
  • @yaodav 似乎有帮助,我会调查一下; @kjpus 我考虑过,但是someFunctionsomeOtherFunction 分别接受每个参数,因为它们不是我的代码,所以不能更改它们的签名。
  • 我认为我之前的回答完美地回答了你,除非你误解了什么。
  • 我仍在尝试了解这些答案中的任何一个如何检查所有要求。这一次,他们都没有考虑如何将参数顺序传递给boost::bind,这确实是我的主要问题。再说一次,我承认我对这种静态编程没有太多经验。

标签: c++ c++11 templates variadic


【解决方案1】:

您可以使用本文 (Produce std::tuple of same type in compile time given its length by a template argument) 中的技巧来生成包含 N 个元素的元组。

template <int N, typename T> 
struct tuple_n_impl {
    template <typename... Ts> 
    using type = typename tuple_n_impl<N - 1, T>::template type<T, Ts...>;
};

template <typename T> 
struct tuple_n_impl<0, T> {
    template <typename... Ts> 
    using type = std::tuple<Ts...>;
};

template <int N, typename T>
using tuple_n = typename tuple_n_impl<N, T>::template type<>;

template <int N>
class MyClass {
    void int_function(tuple_n<N, int>&& ints);
    void float_function(tuple_n<N, float>&& floats);

    template <typename T> 
    void any_function(tuple_n<N, T>&& elements);
};

【讨论】:

  • 简洁的解决方案(我将保存元组技巧以备后用),但这需要函数参数是元组,对吗?我无法更改函数的原型。
  • 不是真的,您可以使用参数包 + 元组来访问索引。或者你可以使用一个数组。你可以做类似template &lt;typename... Ts&gt; void int_function(Ts&amp;&amp;... elements) { int_function(std::make_tuple(std::forward&lt;Ts&gt;(elements)...); }的事情。不过,此解决方案确实需要为每个实现提供两种方法。
【解决方案2】:

您可能会使用std::index_sequence(C++14,但可以在 SO 上找到 C++11 中的实现):

template <std::size_t, typename T>
using always_t = T;

template <std::size_t ... Is>
class MyClassImpl {
    using MyDepType = SomeType<always_t<Is, int>...>;
    void myFunction(always_t<Is, std::string>... args) { /* do stuff */}
 public:
    MyClass() {
        void someFunction(always_t<Is, std::float>... args);
        someOtherFunction([this](always_t<Is, const std::string&>... args) {
            return myFunction(args...);
        });

        // 
        std::array<std::string, sizeof...(Is)> strings = {std::to_string(Is)...};
        myFunction(strings[Is]...);
    };
};

template <std::size_t N>
using MyClass = MyClassImpl<std::make_index_sequence<N>>;

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 2021-09-21
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多