用作函数参数时如何定义到 class 模板的转换

How to define conversion to class template working when used as function argument

拥有此模板:

template <bool X> 
struct Foo {
  Foo(int v) : v(v) {}
  int v;
};

我可以说默认情况下 Foo 应该是 False 推导指南:

Foo(int)->Foo<false>;

感谢这段代码的工作:

Foo a = 5;

我的问题是,当 Foo 用作函数参数时,我怎样才能使它工作:

template <bool X> 
void f(Foo<X> foo) { 
  cout << "Foo<" << X << ">(" << foo.v << ")" << endl; 
}
f(5); // error: no matching function for call to 'f'
      // candidate template ignored: could not match 'Foo<X>' against 'int'

我试过以某种方式说 f 默认情况下 X false 但是 f(我的意思是编译器)没有听我说:

template <bool X = false> // = false changes nothing, same error 
void f(Foo<X> foo) {
  cout << "Foo<" << X << ">(" << foo.v << ")" << endl; 
}
template <bool X> 
struct get_bool { // to force looking at f::X 
  static constexpr bool value = X; 
};

template <bool X = false> 
void f(Foo<get_bool<X>::value> foo) { 
  cout << "Foo<" << X << ">(" << foo.v << ")" << endl;         
  /* this is not working because 
   * get_bool evaulates before 
   * args matching and in the end, 
   * this function could be defined 
   * as: void f(Foo<false>) 
   */
}

我不介意引入一些额外的助手 classes 等等。 我希望也许一些 decltypeautosome_trait<> 或其他助手 class (/es) 魔法可以帮助解决这个问题,我想我也可以总结一下上升为: 如何定义函数的演绎指南?

template <bool X = false> void f(Foo<X> foo) 的问题是,在将参数传递给模板参数推导中使用的参数时,不允许隐式转换。

您可以添加额外的 f 重载以接受 int,或者根本不使 f 成为模板:

struct Bar
{
    bool x = false;
    int v = 0;

    template <bool X>
    Bar(Foo<X> foo) : x(X), v(foo) {}

    Bar(int v) : v(v) {}
};

void f(Bar bar) {...}

这意味着布尔值不再是 constexprf 内。如果你想让它成为 constexpr,你可以使用一个技巧:

void f(Bar bar)
{
    auto lambda = [&](auto x_value)
    {
        constexpr bool x = x_value;
        // Here `x` is `constexpr`.
    };

    if (bar.x)
        lambda(std::true_type{});
    else
        lambda(std::false_type{});
}