是否可以返回模板函数指定的类的成员变量?

Is it possible to return a member variable of a class specified by a template function?

提问人:ModernEraCaveman 提问时间:7/3/2023 最后编辑:JeJoModernEraCaveman 更新时间:7/3/2023 访问量:122

问:

我正在尝试为我正在编写的游戏引擎通用一个函数,以简化着色器加载过程。

无论如何,在我尝试模板化函数时出现了困难。我试图调整此堆栈线程中的解决方案,并导致以下代码的各种版本,但没有任何理想的解决方案:

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'

我知道返回的值与 不是同一类型,因为与 .xUint testS1::*int

但是,我不明白我将使用什么语法从结构中返回类型的成员变量。xUT

占位符后面的真实结构彼此非常不同,因此如果可能的话,我想避免使用基类/结构。testS1testS2

C++ 模板 指针到成员 函数模板 C++20

评论


答:

4赞 YSC 7/3/2023 #1
template<class T, class U, U T::*x>
U testFunc(T& t)
{
    return t.*x;
}

您只需取消引用即可获得 .xU

评论

0赞 ModernEraCaveman 7/3/2023
你是我的英雄 <3 我试过 'return *x;' 所以 idk 为什么 'return t.*x;' 我从来没有想过!非常感谢。
4赞 JeJo 7/3/2023 #2

另一个答案已经提供了用于访问指向成员数据的指针的语法。在 中使用缩写函数模板,您可以这样做,不那么冗长

template<auto  x>
constexpr auto testFunc(auto const& t)
{
    return t.*x;
}

现在,您可以使用不太明确的模板参数进行调用

int c = testFunc<&testS1::a>(tS1);
bool d = testFunc<&testS2::b>(tS2);
// ...

观看演示 godbolt.org

评论

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