如何使用“using”关键字来处理可变模板参数

4
我有一个可变参数模板类,可以在构造函数中接受任意数量的变量,也可以接受std::tuple/std::pair等类型。
我想使用这个包装器来处理具有不同返回类型的函数。
例如:
class f1
{
    using output = double;
    output operator() { do_smth };
}
class f2
{
    using output = std::tuple<double,int>;
    output operator() { do_smth };
}



template <typename... Types>
class OutputType
{
    std::tuple<Types...> m_val;
public:
    OutputType(std::tuple<Types...>&& val) : m_val(val) {};
    OutputType(Types&& ... val) : m_val(std::forward<Types>(Types)...) {};
};

现在在第三个类中,我想声明使用方式如下:
template <typename F>
class dummy
{
    using Output = typename OutputType(typename F::Output));
}

如何声明上述使用语句,以便它也适用于 dummy<f2>
(即 OutputType<double,int> 而不是 OutputType<std::tuple<double,int>>

你能提供一个至少能够运行 f1 的代码吗?你的代码包含了很多排版错误... 你在这里需要做的可能是为 std::tuple 特化 dummy - Holt
你可能可以将元组转换为参数包并将该包发送到“OutputType”。不确定它会是什么样子。但是,已经有很多关于将元组转换为参数包的内容了。 - NathanOliver
2个回答

5

如果我正确理解您的问题,您可以将类型特征定义为

template <typename ... Types>
struct oTypes
 { using type = OutputType<Types...>; };

template <typename ... Types>
struct oTypes<std::tuple<Types...>>
 { using type = OutputType<Types...>; };

然后按照以下方式定义dummy

template <typename F>
struct dummy
 { using output = typename oTypes<typename F::output>::type; };

以下是一个完整可编译的示例。
#include <tuple>
#include <utility>

struct f1
 {
   using output = double;

   output operator() ()
    { return 0.0; }
 };

struct f2
 {
   using output = std::tuple<double,int>;

   output operator() ()
    { return { 1.0, 2 }; }
 };

template <typename ... Types>
class OutputType
 {
   private:
      std::tuple<Types...> m_val;

   public:
      OutputType(std::tuple<Types...>&& val) : m_val(val)
       { }

      OutputType(Types&& ... val) : m_val(std::forward<Types>(val)...)
       { }
 };

template <typename ... Types>
struct oTypes
 { using type = OutputType<Types...>; };

template <typename ... Types>
struct oTypes<std::tuple<Types...>>
 { using type = OutputType<Types...>; };

template <typename F>
struct dummy
 { using output = typename oTypes<typename F::output>::type; };

int main()
 { 
   static_assert( std::is_same<dummy<f1>::output,
                               OutputType<double>>::value, "!");
   static_assert( std::is_same<dummy<f2>::output,
                               OutputType<double, int>>::value, "!!");
 }

这正是我所问的。这是一个相当聪明的解决方案。我考虑过使用decltype(),但无法弄清楚如何正确地编写它。 - Buck B

1

一个辅助模板,例如

template<typename ... Types>
struct add_tuple {
    using type = std::tuple<Types...>
};

template<typename ... Types>
struct add_tuple<std::tuple<Types...>> {
    using type = std::tuple<Types...>
};

将OutputType更改为类似以下内容的东西。
template <typename... Types>
class OutputType
{
    typename add_tuple<Types...>::type m_val;
public:
    OutputType(typename add_tuple<Types...>::type&& val) : m_val(val) {};
    OutputType(Types&& ... val) : m_val(std::forward<Types>(Types)...) {};
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接