【问题标题】:implicitly finding the template variable typename隐式查找模板变量类型名
【发布时间】:2014-01-20 17:19:03
【问题描述】:

我有这些功能:

template<class Route, bool enabled=true>
inline void addRoute() {
    if(!enabled) return;       
    routes.push_back(Route({}, {}));
}

template<class Route, bool enabled=true, class... Args>
inline void addRoute(Args&&... args, std::vector<LogLevel>&& levels_ = {},
                 std::vector<String>&& categories_={}) {
    if(!enabled) return;
    if(!removeLowerLevels(levels_)) return; 
    routes.push_back(Route(std::forward<Args>(args)..., levels_, categories_));
}

这个函数应该传递“主要”参数(任何 Route 类的级别_和类别_);如果派生类之一中有任何附加参数,也可以将其传递给路由。我希望此功能以多种方式工作:

//1. takes no additional arguments
addRoute<ConsoleLogRoute, DEBUG>({LogLevel::Notice}, {"system"});
//2. Takes no additional or main arguments
addRoute<SomeCustomLogRoute>();
//3. Takes additional arguments but no main arguments
addROute<HtmlLogRoute>("textFile.html", HtmlLogRoute::MakeBulletLists);
//4. Takes any amount of additional arguments
addRoute<FileLogRoute>("filename.log", {LogLevel::Info}, {"application"});

1 和 2 按预期工作。但是3和4编译失败:

Error: Candidate function requires at most 2 arguments, but X were provided.(X 为 3 或 4)

我通过为Args 提供变量来修复此错误:

addRoute<FileLogRoute, true, String>("filename.log", {LogLevel::Info}, {"application"});

我的问题是:

我该怎么做才能不显式编写变量类型名?比如这个printf example(取自here)。

【问题讨论】:

  • std::tuple 在您想要传递分配器时也有类似的问题。它在标准库中通过传递标签来解决,请参阅en.cppreference.com/w/cpp/utility/tuple/tuple 中采用std::allocator_arg_t 的重载
  • 你能把“附加参数”放在前面吗?这是迄今为止最简单的方法。
  • 请注意,它可以按照您的方式解决。我只是对物有所值的解决方案持怀疑态度。
  • @Yakk 过了一会儿,我意识到我最好使用良好的旧指针/引用传递:)

标签: c++ c++11


【解决方案1】:

让我们看一个更简单的例子:

  // declare something to call, just for filler.
int sum(int i) { return i ; }
template <class T, class... A> int sum(T v, A&&... vs) { return v + sum( vs... ) ; }

template < class... A >
  int process( A&&... a, int val )  
{   
  return sum( val, a... ) ;  
}

int main()
{   
  int i ;  

  i= process( 10) ;  
  i= process( 10, 1 ) ;   // fail

  return 0 ;  
}  

通过将参数 int val 放在可变模板参数之后,GCC 和 Clang 都将 A&amp;&amp; 的参数列表设置为零。如果你交换位置,它工作正常。所以基本上A&amp;&amp;... 是非贪婪的,如果你在它后面加上任何其他参数,它默认为空。

正如您所发现的,通过显式声明类型,它会起作用,所以在这种情况下

i= process<int>( 10, 1 )

会起作用的。

【讨论】:

  • 是的,但关键是不要显式声明类型。我这样做不是为了表演或任何事情。只是为了简单。
猜你喜欢
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 2022-11-15
  • 1970-01-01
  • 2011-11-19
  • 1970-01-01
相关资源
最近更新 更多