首页 > 解决方案 > 用作函数参数时如何定义转换为类模板工作

问题描述

有这个模板:

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'

我试着以某种方式fX默认情况下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>) 
   */
}

我不介意引入一些额外的辅助类等。我希望也许一些decltype,autosome_trait<>额外的辅助类 (/es) 魔法可以帮助解决这个问题,我想我也可以总结为:如何定义一个功能推导指南?

标签: c++templatesc++17compile-time

解决方案


问题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) {...}

这意味着布尔值不再constexpr位于f. 如果你想要它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{});
}

推荐阅读