【问题标题】:How to specialize template pack?如何专注于模板包?
【发布时间】:2016-10-04 15:10:55
【问题描述】:

我有以下代码,它试图将二进制数(作为布尔值列表传递,最低有效位在前,可变长度)转换为十进制数:

#include <iostream>
using namespace std;

template<typename T>
int bin_to_dec(int multi, T first) {
    cout<<"mutli"<<multi<<endl;
  return first?multi:0;
}

template<typename T, typename... Args>
int bin_to_dec(int multi, T first, Args... args) {
    cout<<"mutli"<<multi<<endl;
  return (first?multi:0) + adder(multi*2, args...);
}

template<typename T, typename... Args>
int bin_to_dec(T first, Args... args) {
    cout<<"mutli"<<1<<endl;
  return (first?1:0) + adder(2, args...);
}

int main()
{
    cout<<bin_to_dec(true, true, false, true)<<endl;
}

它工作得很好,但我想让它只适用于布尔值,所以当我尝试像 bin_to_dec(1,2,3) 这样的东西时,它不应该编译。我试图使用类似的东西

template<bool First, bool... Bools>

但我不知道如何更进一步。有什么想法吗?

【问题讨论】:

标签: c++ templates c++11 variadic-templates template-specialization


【解决方案1】:

显而易见的方法是从所有模板参数的重载集中删除函数,但bool

template <typename... T>
std::enable_if_t<variadic_and(std::is_same<T, bool>::value...), int>
bin_to_dec(T... bits) {
    // probably delegate to differently named functions as an implementation detail
    // ...
}

variadic_and() 将是一个 constexpr 函数,如果其所有参数都是 true,则返回 true

constexpr bool variadic_and() { return true; }
template <typename... T>
constexpr bool variadic_and(bool v, T... vs) {
    return v && variadic_and(vs...);
}

对于 C++17,variadic_and() 是必需的,因为可以使用运算符扩展参数包。例如,variadic_and() 的实现可能如下所示:

template <typename... T>
constexpr bool variadic_and(T... vs) { return (vs && ...); }

同样的方法可以直接在std::enable_if_t&lt;...&gt;中使用。

注意:上面使用的方法要求参数被推断为bool,即它们几乎需要是bool 类型。由于函数不应使用int 参数调用,并且这些参数将转换为bool,因此测试参数类型是否可转换为bool 似乎不合适。但是,可能允许一些转换是合理的。如果是这样,则将在std::enable_if_t 的第一个参数中使用相应的特征。

【讨论】:

  • std::enable_if_t &lt;std::conjunction&lt; std::is_same&lt;T, bool&gt;...&gt;{}, int&gt;for c++17
【解决方案2】:

只需使用静态断言。这很好用:

int bin_to_dec() {
    return 0;
}

template<typename T, typename ... Args>
int bin_to_dec(T first, Args ... rest)
{
    static_assert(std::is_same<bool, T>::value, "Only valid for bools");
    return (first ? 1 : 0) + (bin_to_dec(rest...) << 1);
}

int main()
{
    cout<<bin_to_dec(true, true, false, true)<<endl;
    cout<<bin_to_dec(1, 2, 3)<<endl;  //compile error
}

【讨论】:

  • 我不太理解反对票。上面的代码完全按照 OP 的要求工作,即用bools 给出正确的答案,并且不能用其他任何东西编译。我看不出上面的评论有什么相关性,因为 OP 从未要求从重载集中删除函数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多