我有一个班。Delegate
,像这样声明。
template<typename T> class Delegate;
template<typename R, typename... Args>
class Delegate<R(Args...)>
{ /*...*/ };
它可以被实例化为一个函数,返回一个... ReturnType
不以为然 Delegate<ReturnType()>
. 我遇到了一个问题,需要我把类的功能专门化。()
操作符,但一直想不出如何迫使编译器这样做而不出现编译错误。
我有以下函数。
template <typename R, typename... Args>
R Delegate<R(Args...)>::operator()(Args... args)
{ /*...*/ }
添加下面的特殊化,我得到一个错误的信息说 invalid use of incomplete type 'class Delegate<R()>'
:
template <typename R>
R Delegate<R()>::operator()()
{ /*...*/ }
但我不能简单地替换 Args...
与 void
或者,据我所知... ... 在这里,正确的程序是什么,(如果这个问题适用,你觉得特别有用的话)为什么?
你尝试使用 R Delegate<R()>::operator()()
专攻 更加 由于§14.5.5.3 [temp.class.spec.mfunc],类模板的部分特殊化的成员函数失败。
1 类模板局部特殊化的成员的模板参数列表应与类模板局部特殊化的模板参数列表相匹配。
换句话说。
template <typename R>
R Delegate<R()>::operator()() { /**/ }
实际上是一个特殊化的 operator()
你的 主模板:
template <typename T>
class Delegate;
由于它是一个不完整的类型,你最终会出现错误。可能的变通方法有
对整个类进行专门化,并重新实现该类的所有成员。
template <typename T>
class Delegate;
template <typename R, typename... Args> // partial specialization for non-empty Args
class Delegate<R(Args...)>
{
R operator()(Args...) { return {}; }
};
template <typename R> // partial specialization for empty Args
class Delegate<R()>
{
R operator()() { return {}; }
};
多用一个专门的委托类。
#include <utility>
template <typename T>
struct Impl;
template <typename R, typename... Args>
struct Impl<R(Args...)>
{
static R call(Args&&...) { return {}; }
};
template <typename R>
struct Impl<R()>
{
static R call() { return {}; }
};
template <typename T>
class Delegate;
template <typename R, typename... Args>
class Delegate<R(Args...)>
{
R operator()(Args... args)
{
return Impl<R(Args...)>::call(std::forward<Args>(args)...);
}
};
使用一些丑陋的SFINAE。
#include <type_traits>
template <typename T>
class Delegate;
template <typename R, typename... Args>
class Delegate<R(Args...)>
{
template <typename T = R>
typename std::enable_if<sizeof...(Args) != 0 && std::is_same<T,R>{}, R>::type
operator()(Args...) { return {}; }
template <typename T = R>
typename std::enable_if<sizeof...(Args) == 0 && std::is_same<T,R>{}, R>::type
operator()() { return {}; }
};
从一个专门的类模板继承,可能会利用 CRTP 习语。
template <typename T>
class Delegate;
template <typename T>
struct Base;
template <typename R, typename... Args>
struct Base<Delegate<R(Args...)>>
{
R operator()(Args...)
{
Delegate<R(Args...)>* that = static_cast<Delegate<R(Args...)>*>(this);
return {};
}
};
template <typename R>
struct Base<Delegate<R()>>
{
R operator()()
{
Delegate<R()>* that = static_cast<Delegate<R()>*>(this);
return {};
}
};
template <typename R, typename... Args>
class Delegate<R(Args...)> : public Base<Delegate<R(Args...)>>
{
friend struct Base<Delegate<R(Args...)>>;
};