用作函数参数时如何定义到 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 等等。
我希望也许一些 decltype
、auto
、some_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) {...}
这意味着布尔值不再是 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{});
}
拥有此模板:
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 等等。
我希望也许一些 decltype
、auto
、some_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) {...}
这意味着布尔值不再是 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{});
}