在下面的类中,我尝试将一个类型擦除函数特化为一个空类型,用于默认初始化的情况,然而,这会产生下面的error: explicit specialization in non-namespace scope
.现在我已经做了研究,了解到gcc由于某种原因不允许在类作用域中进行完全模板特化,因此我必须把它从类中拉出来,放到命名空间作用域中。然而这给我留下了更大的痛苦,正如你所看到的,类模板参数被用来将参数转发给一个外部函数,所以我也必须将其模板化,但是话又说回来,我不能将函数模板部分地专门化,因为Args...是一个模板并且只专门化于empty_t
。我该如何优雅地解决这个问题?
演示
#include <utility>
#include <cstdio>
template <typename... Ts>
void myfunc(Ts... args)
{
printf("Do something!\n");
}
template <typename R, typename... Args>
struct entity;
template <typename R, typename... Args>
struct entity<R(Args...)>
{
using fn_invoke_t = R(*)(void*);
struct empty_t{};
template <typename T>
static R fn_invoke(Args&&... args) {
return myfunc(args...);
}
template <>
static R fn_invoke<empty_t>(Args&&... args) {
return myfunc(args...);
}
entity()
: fn_invoke_(reinterpret_cast<fn_invoke_t>(fn_invoke<empty_t>))
{ }
template <typename T>
entity(T obj)
: fn_invoke_( reinterpret_cast<fn_invoke_t>(fn_invoke<T>) )
{ }
fn_invoke_t fn_invoke_;
};
int main()
{
entity<void()> hello = [](){ printf("Hello World!\n"); };
// hello();
}
错误:
<source>:27:15: error: explicit specialization in non-namespace scope 'struct entity<R(Args ...)>'
27 | template <>
| ^
<source>:28:14: error: template-id 'fn_invoke<entity<R(Args ...)>::empty_t>' in declaration of primary template
28 | static R fn_invoke<empty_t>(Args&&... args) {
3条答案
按热度按时间gt0wga4j1#
你可以改为函数模板重载。
LIVE
xtfmy6hx2#
一种变体可能是完全放弃专门化,而支持模板内的
if constexpr
,例如:如果需要,您可以删除
std::remove_cv_t<std::remove_reference_t<T>>
或C++20std::remove_cvref_t<T>
等类型限定符,以便const
和volatile
类型或引用得到相同的处理。在您的情况下,这将导致:
在godbolt上演示。
yfwxisqw3#
您还可以添加中间阶段:一个“helper”类模板,并在
entity
类之外对其进行专门化(如果要使用静态函数或operator(),则由您调用):这样,就可以避免不可能对函数进行部分专门化。
然后在实体类内部:
https://godbolt.org/z/ehYYvnofE