作者:里 | 来源:互联网 | 2022-12-06 18:37
以下代码不起作用,因为推断模板参数F是std::tuple
,而我希望它是Foo
- 前者采用两个模板参数,后者采用一个.
#include
template
using Foo = std::tuple;
template class F>
void foo(F bar) {}
void test() {
foo(Foo());
}
有没有办法让类型推断与using
语句一起工作而不是Foo
变成它自己的类?
#include
template
class Foo {
std::tuple bar;
};
template class F>
void foo(F bar) {}
void test() {
foo(Foo());
}
更多信息
我正在使用C++ 17 std::variant
以及在单个类型上使用别名类型的别名,我宁愿用using
语句声明这些,而不是为每个语句创建包装类.像这样的东西:
// Assuming Plus, Minus, etc all exist
template
using Operation = std::variant, Minus, Times>;
构建Haskell风格的Functor
这个练习的目的是基于Haskell的仿函数类型类松散地构建一个小的仿函数库.我已经像这样定义了"类型类":
template class F>
class Functor {
public:
template
static F fmap(std::function f, F functor);
};
但是我也想添加一些糖,这样你就可以创建一个通用映射器,它可以在任何函数类型上映射函数,而无需预先指定仿函数类型:
template
struct FMap {
FMap(std::function f) : f_(f) {}
template class F>
F operator()(F functor) {
return Functor::fmap(f_, functor);
}
private:
std::function f_;
};
template
FMap fmap(std::function f) {
return FMap(f);
}
这适用于一个简单的值包装器仿函数:
template
class Value {
public:
Value(T value) : value_(value) {}
const T& value() const {
return value_;
}
private:
T value_;
};
template <>
template
Value Functor::fmap(std::function f, Value value) {
return Value(f(value.value()));
}
void test() {
std::function fn = [](int x) {
return std::to_string(x);
};
auto result = fmap(fn)(Value(42));
// result.value() == "42"
}
现在我试图让它与上面例子中使用std::tuple
或std::variant
类似的更复杂的类型一起工作.
template <>
template
Foo Functor::fmap(std::function f, Foo value) {
return Foo(std::get<0>(value), f(std::get<1>(value)));
}
void test() {
std::function fn = [](int x) {
return std::to_string(x);
};
// This is the desirable syntax but it doesn't build
// fmap(fn)(Foo(42, 7));
// This builds but it's super ugly
fmap(fn).operator()(Foo(42, 7));
}
基于下面SkepticalEmpiricist的回应,我认为类型别名可能不是这里的方式,而是我将不得不引入小包装类 - 除非有一个SFINAE方法可以使这个工作.
这个库主要是一种好奇心,也是我探索更高级模板概念的手段 - 感谢您的帮助!