Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以分开编译时策略的创建和使用位置吗?_C++_Templates_Compile Time - Fatal编程技术网

C++ 我可以分开编译时策略的创建和使用位置吗?

C++ 我可以分开编译时策略的创建和使用位置吗?,c++,templates,compile-time,C++,Templates,Compile Time,有没有类似的方法?或者某种完全不同的模式(但不是运行时多态性\虚拟函数)来解决这个问题 在我的应用程序中,p.S.算法有几个子算法作为参数,子算法也有类似的结构。此外,一些子算法具有不同的创建接口。对于运行时多态性,我可以使用某种工厂模式,整个过程看起来不错(),但我确实不能在这里使用虚拟函数 p.p.S.我怀疑问题的措辞是否反映了我在代码中实际提出的问题,因此我很乐意得到任何建议。您应该使用一个接口,同时使用SubAlgorithm1和SubAlgorithm2(您需要更好的名称)实现接口。根

有没有类似的方法?或者某种完全不同的模式(但不是运行时多态性\虚拟函数)来解决这个问题

在我的应用程序中,p.S.算法有几个子算法作为参数,子算法也有类似的结构。此外,一些子算法具有不同的创建接口。对于运行时多态性,我可以使用某种工厂模式,整个过程看起来不错(),但我确实不能在这里使用虚拟函数


p.p.S.我怀疑问题的措辞是否反映了我在代码中实际提出的问题,因此我很乐意得到任何建议。

您应该使用一个接口,同时使用SubAlgorithm1和SubAlgorithm2(您需要更好的名称)实现接口。根据运行时标志创建任一类的对象。

是。我把这种技术称为魔术开关

创建算法的
std::tuple
。您可以创建一个模板函数,该函数将通过这些算法之一传递

如果需要,可以通过完美变量转发添加其他参数

TypeClass SubAlgorithm = runtime_flag : SubAlgorithm1 ? SubAlgorithm2;
SubAlgorithm sub_algorithm;
Algorithm(sub_algorithm, stuff);
模板
bool magic_开关(int n,Func&f,std::tuple const&pick){
如果(n==Max-1){
f(std::get(pick));
返回true;
}否则{
返回幻灯开关(n,标准::前进(f),拾取);
}
}
在伪代码中。Specialize Max==0以仅返回false,您可能必须将其设为函子,以便进行部分专门化

作为缺点,传入的functor编写起来很烦人

另一种变体是使用元工厂(好吧,元编程类型工厂?可能是元映射。好吧,随便吧。)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//元编程样板文件:
模板
结构元组映射;
模板
结构元组映射{
typedef L<工厂…>类型;
};
模板
使用MapTuple=typename tuple\u map::type;
模板结构seq{};
模板
结构make_seq:make_seq{};
模板
结构制造{
typedef-seq-type;
};
模板
使用MakeSeq=typename make_seq::type;
//整洁的小类,可以让您键入或删除元组的内容,
//并将其转换为均匀阵列:
模板
结构元组数组;
模板
结构元组数组{
模板
std::array操作符()(L const&src,seq)const{
数组retval{DestType(std::get(src))…};
返回返回;
}
std::array操作符()(L const&src)const{
return(*this)(src,MakeSeq());
}
};
模板
自动DoTupleToArray(SourceTuple const&src)
->decltype(TupleToArray()(src))
{
返回TupleToArray()(src);
}
//从这里开始的代码实际上是针对这个问题的:
struct SubAlgo{int operator()(int x)const{return x;}};
struct SubAlgo2{int operator()(int x)const{return x+1;}};
模板
结构完整算法{
void运算符()(std::vector&v)常量{
用于(自动和x:v)
x=Sub()(x);
}
};
//有点乱,但我想我可以清理一下:
typedef std::tuplesubAlgos;
MapTuplefullAlgos;
typedef std::functionfuncType;
std::arrayfullAlgoArray=
DoTupleToArray(fullAlgos);
int main(){
std::向量测试{1,2,3};
完整阵列[0](测试);
用于(自动和x:测试)

std::cout无论您在运行时做什么,都会像您的
if
子句一样不雅观和直接,或者通过指针、引用或虚拟表调用某种间接寻址。但是,间接寻址可以在顶层而不是在最内层循环中,因此性能几乎不会受到影响。我似乎记得有一个选项是de在命令行中使用一个宏来解决这个问题。这很可爱。它本质上与OP的原始设计相同(避免间接寻址的唯一方法,请参阅我的注释),但是
if
块隐藏在
magic_开关()中
@Walter当然,添加更多类型需要更高的
Max
和更大的元组。如果需要,您还可以从元组的类型推断
Max
。实际上,我正在让编译器在顶层为我编写嵌套的
if
语句。您也可以使用此技术的变体nique生成应用了
子算法类型的
std::function
s的类型擦除数组,然后通过数组查找调用该函数。
TypeClass SubAlgorithm = runtime_flag : SubAlgorithm1 ? SubAlgorithm2;
SubAlgorithm sub_algorithm;
Algorithm(sub_algorithm, stuff);
template<size_t Max, typename...Ts, typename Func>
bool magic_switch( int n, Func&& f,  std::tuple<Ts...> const & pick ) {
  if( n==Max-1 ) {
    f(std::get<Max-1>(pick));
    return true;
  } else {
    return magic_switch<Max-1>( n, std::forward<Func>(f), pick );
  }
}
#include <iostream>
#include <tuple>
#include <vector>
#include <utility>
#include <cstddef>
#include <functional>
#include <array>
#include <iostream>

// metaprogramming boilerplate:
template<template<typename>class Factory, typename SourceTuple>
struct tuple_map;
template<template<typename>class Factory, template<typename...>class L, typename... SourceTypes>
struct tuple_map<Factory, L<SourceTypes...>> {
  typedef L< Factory<SourceTypes>... > type;
};
template<template<typename>class Factory, typename SourceTuple>
using MapTuple = typename tuple_map<Factory, SourceTuple>::type;
template<std::size_t...> struct seq {};
template<std::size_t max, std::size_t... s>
struct make_seq: make_seq<max-1, max-1, s...> {};
template<std::size_t... s>
struct make_seq<0, s...> {
  typedef seq<s...> type;
};
template<std::size_t max>
using MakeSeq = typename make_seq<max>::type;

// neat little class that lets you type-erase the contents of a tuple,
// and turn it into a uniform array:
template<typename SourceTuple, typename DestType>
struct TupleToArray;
template<template<typename...>class L, typename... Ts, typename DestType>
struct TupleToArray<L<Ts...>, DestType> {
  template<std::size_t... Index>
  std::array< DestType, sizeof...(Ts) > operator()( L<Ts...> const& src, seq<Index...> ) const {
    std::array< DestType, sizeof...(Ts) > retval{ DestType( std::get<Index>(src) )... };
    return retval;
  }

  std::array< DestType, sizeof...(Ts) > operator()( L<Ts...> const& src ) const {
    return (*this)( src, MakeSeq<sizeof...(Ts)>() );
  }
};
template< typename DestType, typename SourceTuple >
auto DoTupleToArray( SourceTuple const& src )
  -> decltype( TupleToArray<SourceTuple, DestType>()( src ) )
{
  return TupleToArray<SourceTuple, DestType>()( src );
}

// Code from here on is actually specific to this problem:
struct SubAlgo { int operator()(int x) const { return x; } };
struct SubAlgo2 { int operator()(int x) const { return x+1; } };

template<typename Sub>
struct FullAlgo {
  void operator()( std::vector<int>& v ) const {
    for( auto& x:v )
      x = Sub()( x );
  }
};

// a bit messy, but I think I could clean it up:
typedef std::tuple< SubAlgo, SubAlgo2 > subAlgos;
MapTuple< FullAlgo, subAlgos > fullAlgos;
typedef std::function< void(std::vector<int>&) > funcType;
std::array< funcType, 2 > fullAlgoArray =
  DoTupleToArray< funcType >( fullAlgos );

int main() {
  std::vector<int> test{1,2,3};
  fullAlgoArray[0]( test );
  for (auto&& x: test)
    std::cout << x;
  std::cout << "\n";
  fullAlgoArray[1]( test );
  for (auto&& x: test)
    std::cout << x;
  std::cout << "\n";
}