提问人:ModernEraCaveman 提问时间:7/3/2023 最后编辑:JeJoModernEraCaveman 更新时间:7/3/2023 访问量:122
是否可以返回模板函数指定的类的成员变量?
Is it possible to return a member variable of a class specified by a template function?
问:
我正在尝试为我正在编写的游戏引擎通用一个函数,以简化着色器加载过程。
无论如何,在我尝试模板化函数时出现了困难。我试图调整此堆栈线程中的解决方案,并导致以下代码的各种版本,但没有任何理想的解决方案:
template<typename T, typename U, U T::* x>
U testFunc(T& t)
{
// Simplification of the extremely generalized function;
// I want to return/utilize member variable x of input t
return x;
}
struct testS1 { int a = 100; };
struct testS2 { bool b = true; };
testS1 tS1;
testS2 tS2;
// would ideally return 100
int c = testFunc<testS1, int, &testS1::a>(tS1);
// would ideally return true
bool d = testFunc<testS2, bool, &testS2::b>(tS2);
运行程序时会出现以下错误:
Severity: Error
Line: 46
Code: C2440
Description: 'return': cannot convert from 'int testS1::* ' to 'U'
我知道返回的值与 不是同一类型,因为与 .x
U
int testS1::*
int
但是,我不明白我将使用什么语法从结构中返回类型的成员变量。x
U
T
占位符后面的真实结构彼此非常不同,因此如果可能的话,我想避免使用基类/结构。testS1
testS2
答:
4赞
YSC
7/3/2023
#1
template<class T, class U, U T::*x>
U testFunc(T& t)
{
return t.*x;
}
您只需取消引用即可获得 .x
U
评论
0赞
ModernEraCaveman
7/3/2023
你是我的英雄 <3 我试过 'return *x;' 所以 idk 为什么 'return t.*x;' 我从来没有想过!非常感谢。
4赞
JeJo
7/3/2023
#2
另一个答案已经提供了用于访问指向成员数据的指针的语法。在 c++20 中使用缩写函数模板,您可以这样做,不那么冗长
template<auto x>
constexpr auto testFunc(auto const& t)
{
return t.*x;
}
现在,您可以使用不太明确的模板参数进行调用
int c = testFunc<&testS1::a>(tS1);
bool d = testFunc<&testS2::b>(tS2);
// ...
评论
0赞
ModernEraCaveman
7/3/2023
感谢您澄清 Pepijn 的回答。如果我想返回一个 std::vector 怎么办?这样一来,调用行和 testFunc 就变成了这样,是否可以将其简化为单个输入模板函数,或者由于内部 std::vector 而没有?std::vector<int> testVec = testFunc<&testS1::a>(tS1);
template<typename T, auto x> constexpr auto testFunc(auto const& srcVec) { std::vector<T>dstVec(srcVec.size()); std::transfer(srcVec.begin(), srcVec.end(), dstVec.begin(), [](auto const& mSrc){ return mSrc.*x; }); return dstVec; }
1赞
JeJo
7/3/2023
@ModernEraCaveman 是的,当然是在帮助者特质的帮助下:gcc.godbolt.org/z/YGb83o3E3
0赞
ModernEraCaveman
7/3/2023
你是个巫师,JeJo!助手特质看起来像是完全的魔术,因为不知道它们是如何工作的,但它起作用了,哈哈。非常感谢您的帮助。
2赞
YSC
7/4/2023
接受我的赞成票。在匆忙中,我错过了这个更好的解决方案。@ModernEraCaveman我不介意这个答案来获得复选标记;)
0赞
ModernEraCaveman
7/4/2023
在它🫡上面,我一直在努力决定给他们复选标记,因为可能不适用于每个用例,但你已经使这个决定变得容易做出。尽管如此,我还是感谢您提供可行解决方案的速度!auto
评论