gpt4 book ai didi

c++ - 编译时的类型特化

转载 作者:IT王子 更新时间:2023-10-29 00:47:01 25 4
gpt4 key购买 nike

我正在编写一个类,它与 std::function 共享几个不同的特性。 (或者至少这些类(class)在很多方面都是相似的)。众所周知std::function通过指定模板参数(即 std::function<void (std::string&)> )实例化,它与我的类(class)相同。不过我有一个异常(exception),如果返回值为 void (std::function<"return value" ("parameters">),我想在我的类中专门化一个 single 函数。我需要在编译时完成这项工作,但我无法让它按预期工作。下面是一些测试代码来解释:

#include <iostream>
#include <type_traits>

template <typename T> class Test { };

template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
Ret operator()(Args...)
{
if(std::is_void<Ret>::value)
{
// Do something...
}

else /* Not a void function */
{
Ret returnVal;
return returnVal;
}
}
};

int main(int argc, char * argv[])
{
Test<void (char)> test;
test('k');
}

您可以清楚地看到,如果编译器没有在上述测试中删除“else”分支,我的代码将尝试创建一个空值(即 void returnVal;)。问题是编译器没有删除分支,所以我最终遇到编译器错误:

./test.cpp: In instantiation of ‘Ret Test::operator()(Args ...) [with Ret = void; Args = {char}]’: ./test.cpp:27:10: required from here ./test.cpp:18:8: error: variable or field ‘returnVal’ declared void ./test.cpp:19:11: error: return-statement with a value, in function returning 'void' [-fpermissive]

通常会使用 std::enable_if结合std::is_void ,问题是我不想专注于 function 模板,而是专注于 class 模板。

template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
Ret returnVal;
return returnVal;
}

typename std::enable_if<std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
// It's a void function
// ...
}
};

如果我改用上面的代码,我会得到更多的错误并且没有解决方案

./test.cpp:11:2: error: expected ‘;’ at end of member declaration
./test.cpp:11:2: error: declaration of ‘typename std::enable_if<(! std::is_void<_Tp>::value), Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:11:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:2: error: expected ‘;’ at end of member declaration
./test.cpp:18:2: error: declaration of ‘typename std::enable_if<std::is_void<_Tp>::value, Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:18:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:6: error: ‘int Test<Ret(Args ...)>::operator()(Args ...)’ cannot be overloaded
./test.cpp:11:6: error: with ‘int Test<Ret(Args ...)>::operator()(Args ...)’
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...)’:
./test.cpp:22:2: warning: no return statement in function returning non-void [-Wreturn-type]
./test.cpp: In instantiation of ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:28:10: required from here
./test.cpp:13:7: error: variable or field ‘returnVal’ declared void
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:15:2: warning: control reaches end of non-void function [-Wreturn-type]

如果我只是愚蠢,我很抱歉,答案是显而易见的。我对模板相当陌生,在任何其他话题/问题中都找不到合适的答案。

最佳答案

从您的描述中,有几件事不是很清楚,所以我将从最笼统的答案开始。

假设模板有其他功能必须保持相同的行为,而您只想重新定义该特定功能的行为,最简单的答案是将模板一分为二,并使用继承来合并它们.此时,您可以在基本模板上使用部分模板特化:

template <typename T, typename... Args>
struct tmpl_base {
T operator()( Args... args ) {
//generic
}
};
template <typename... Args>
struct tmpl_base<void,Args...> {
void operator()( Args... args ) {
}
};

template <typename Ret, typename... Args>
class Test<Ret (Args...)> : tmp_base<Ret,Args...> {
// do not declare/define operator(), maybe bring the definition into scope:
using tmp_base<Ret,Args...>::operator();

// Rest of the class

如果这是您模板中的唯一函数,那么偏特化是一个更简单的解决方案,不需要滥用继承。

关于c++ - 编译时的类型特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11210007/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com