在运行时,元组中的Feed模板函数元素? [英] Feed template function element from tuple at runtime?

查看:133
本文介绍了在运行时,元组中的Feed模板函数元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,我有一个元组,其中包含一些元素:

  std :: tuple< int,char> my_tuple(3,'q'); 

还有一些模板函数完全适用于整数和字符:

 模板< class T> void my_function(T); 

现在,说在运行时我想对我的元组的一个元素运行my_function我不知道是哪个)。我注意到这是不可能做的像:

  unsigned int n; 

//给n赋值n

my_function(std :: get< n>(my_tuple));但是,原则上我需要的应该是相同的:


$ b

  unsigned int n; 

//给一个值n

switch(n)
{
case 0:
my_function(std :: get< ; 0>(my_tuple));
break;
case 1:
my_function(std :: get< 1>(my_tuple));
break;
默认值:
//无操作或抛出异常
}

所以这听起来像我应该是可行的..是吗?

解决方案

/ code>是一个运行时值,它不能用于在编译时实例化模板。您的开关工作,因为您手动实现每个 std :: get< N> ,并将它们连接到相应的运行时值。



但是,写一个大脑切换树有点琐事。为什么不让编译器生成一个TMP的样板?

  #include< tuple> 
#include< cassert>
#include< iostream>

template< class T>
void my_function(T);

//测试专业化看看发生了什么
template<> void my_function(int i){std :: cout< int< i<< '\\\
'; }
template<> void my_function(char c){std :: cout< char< c<< '\\\
'; }

命名空间详细信息{
//在C ++中可用std 14
模板< bool P,class T>
using enable_if_t = typename std :: enable_if< P,T> :: type;

//当enable_if shunts
模板< std :: size_t N,class T = void>时拾取调用的Mockup函数签名。
void callMyFunc(T&&&&& amp; ...){
assert(!Index not in range!
}

//简单递归解决方案,将其自身从重载集中移除
//停止递归
template< std :: size_t N,class ... Ts,
class = enable_if_t< N< sizeof ...(Ts),void>>
void callMyFunc(std :: tuple< Ts ...>& tuple,std :: size_t n){
return n == N
? my_function(std :: get"(tuple))
:callMyFunc< N + 1>(tuple,n)
}
}

//微小的用户友好的包装器
template< class ... Ts>
void callMyFunc(std :: tuple< Ts ...& tuple,std :: size_t n){
detail :: callMyFunc< 0u>(tuple,n);
}

int main(int,char **){
std :: tuple< int,char> my_tuple(3,'q');

//成功。
callMyFunc(my_tuple,0u);
callMyFunc(my_tuple,1u);

return 0;
}


In C++ I have a tuple with some elements in it:

std::tuple <int, char> my_tuple(3, 'q');

And some template function that perfectly works both on integers and chars:

template <class T> void my_function(T);

Now, say that at runtime I want to run my_function on one of the elements of my tuple (but I don't know which). I noticed that it is not possible to do something like:

unsigned int n;

// Give a value to n

my_function(std::get <n> (my_tuple));

However, in principle what I need should be identical to something like:

unsigned int n;

// Give a value to n

switch(n)
{
    case 0:
      my_function(std::get <0> (my_tuple));
      break;
    case 1:
      my_function(std::get <1> (my_tuple));
      break;
    default:
      // Do nothing or throw an exception
}

So it sounds to me like this should be feasible.. is it?

解决方案

n being a runtime value, it can't be used to instanciate a template at compile-time. Your switch works because you manually instanciate each std::get<N>, and wire them to the corresponding runtime value.

But yeah, it's a bit of a chore to write that braindead switch tree. Why not let the compiler generate the boilerplate with a bit of TMP ?

#include <tuple>
#include <cassert>
#include <iostream>

template <class T>
void my_function(T);

// Test specialisations to see what's going on
template <> void my_function(int i) { std::cout << "int " << i << '\n'; }
template <> void my_function(char c) { std::cout << "char " << c << '\n'; }

namespace detail {
    // Available in std in C++14
    template <bool P, class T>
    using enable_if_t = typename std::enable_if<P, T>::type;

    // Mockup function signature to pick up the call when enable_if shunts
    template <std::size_t N, class T = void>
    void callMyFunc(T&&, ...) {
        assert(!"Index not in range !");
    }

    // "Simple" recursive solution, removes itself from the overload set
    // to stop recursion
    template <std::size_t N, class... Ts,
        class = enable_if_t<N < sizeof...(Ts), void>>
    void callMyFunc(std::tuple<Ts...> &tuple, std::size_t n) {
        return n == N
            ? my_function(std::get<N>(tuple))
            : callMyFunc<N + 1>(tuple, n);
    }
}

// Tiny user-friendly wrapper
template <class... Ts>
void callMyFunc(std::tuple<Ts...> &tuple, std::size_t n) {
    detail::callMyFunc<0u>(tuple, n);
}

int main(int, char**) {
    std::tuple <int, char> my_tuple(3, 'q');

    // Success.
    callMyFunc(my_tuple, 0u);
    callMyFunc(my_tuple, 1u);

    return 0;
}

这篇关于在运行时,元组中的Feed模板函数元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆