【发布时间】:2018-05-13 22:06:01
【问题描述】:
我正在围绕 std::function 创建一个模板包装器。为了匹配返回 void 的函数,我将 std::monostate 作为我的 Unit 类型。我一直在尝试为我的函数包装类型创建两个可变参数模板,一个
template<Unit, Args...>
还有一个
template<T, Args...> where T != Unit.
这是我使用 enable_if 得到的最接近的结果。
#include <functional>
#include <variant>
namespace func {
// Declare unit type
typedef std::monostate Unit;
// Empty type, maybe use this instead of monostate
template<typename ... ts>
struct Term {};
// Variables
template<typename T>
struct Term<T>
{
T val;
// Constructor
Term(T in): val(in) {}
// Call op just returns the value
T operator() () const {
return this->val;
}
};
// Functions that return void
template <typename T,
typename ... Args,
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
struct Term<Args...>
{
// Void returning function
const std::function<void(Args...)> body;
// Void returning constructor
Term(std::function<void(Args...)> func): body(func) {}
// Void function Caller
void operator() (const Args&& ...a) const {
this->body(std::forward<Args>(a)...);
}
};
// Functions that return T
template <typename T,
typename ... Args,
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
struct Term<T, Args...>
{
// T returning function
const std::function<T(Args...)> body;
// T returning constructor
Term(std::function<T(Args...)> func): body(func) {}
// T returning function Caller
T operator() (const Args&& ...a) const {
return this->body(std::forward<Args>(a)...);
}
};
}
但是,在第一种情况下,我遇到了关于不可演绎参数 T 的错误。但是,我已经通过我的enable_if 模板参数知道该参数将是Unit 类型。如何让编译器同时接受这两个定义?
错误:
$ clang++ -std=c++17 terms.hpp -pedantic
terms.hpp:29:18: error: default template argument in a class template partial specialization
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
^
terms.hpp:30:9: error: class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct Term<Args...>
^~~~~~~~~~~~~
terms.hpp:27:21: note: non-deducible template parameter 'T'
template <typename T,
^
terms.hpp:29:7: note: non-deducible template parameter (anonymous)
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
^
terms.hpp:47:18: error: default template argument in a class template partial specialization
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
^
terms.hpp:48:9: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct Term<T, Args...>
^~~~~~~~~~~~~~~~
terms.hpp:47:7: note: non-deducible template parameter (anonymous)
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
^
4 errors generated.
编辑:应该这样使用
auto c = Term<int>(42);
auto fun = Term<int, int, int>([](int a, int b) { return a + b; });
std::cout << c() << std::endl;
std::cout << fun(3,4) << std::endl;
【问题讨论】:
-
我相信你应该把匿名的
enable_if参数放在Args之后,而不是之前。 -
@DanielH 很酷,感谢我编辑将 Args 放在匿名模板参数之前。虽然仍然出现同样的错误,所以它可能还没有出现。
-
你打算如何实例化这个模板?
标签: c++ types metaprogramming