gpt4 book ai didi

C++17 if constexpr() 与元组一起使用

转载 作者:行者123 更新时间:2023-11-30 02:21:58 31 4
gpt4 key购买 nike

我正在使用启用了 C++17 支持的 VS2017。

我想尝试创建一个“Transformer”类,当提供某种受支持的类型时,它会转换该类型,否则它将按原样返回变量。目标是将所有变量类型传递给转换器,并“隐藏”它正在转换的变量。这样,调用者可以尝试转换所有内容,而无需担心是否需要转换,转换器会知道。

一个更完整的例子(从原来的编辑而来):

    class MyPoint
{
public:
int x = 0;
};

class NotMyPoint
{
public:
int x = 50;
};

template <typename T>
class ITransform
{
public:

virtual ~ITransform() {};

virtual T InTransform(const T &in) const = 0;

virtual T OutTransform(const T &out) const = 0;

//Check if the argument type is the same as this class type
template <typename X>
constexpr bool CanTransform() const
{
return std::is_same<X, T>::value;
}
};

class MyTransformer :
public ITransform<MyPoint>
{
public:
MyTransformer() = default;

virtual MyPoint InTransform(const MyPoint &in) const override
{
auto newPt = in;
newPt.x += 100;
return newPt;
}

virtual MyPoint OutTransform(const MyPoint &in) const override
{
auto newPt = in;
newPt.x -= 100;
return newPt;
}
};

template <class... TRANSFORMERS>
struct VariadicTransformer
{
constexpr VariadicTransformer() = default;

/** \brief parse using validateParse but catch throw */
template <typename T>
inline T Transform(const T& in)
{
return TransformImpl<sizeof...(TRANSFORMERS)-1, T>(in);
}

private:
/// last attempt to find matching transformer at I==0, if it fails return the original value
template<std::size_t I = 0, typename T>
inline typename std::enable_if<I == 0, T>::type TransformImpl(const T &in) const
{
if (std::get<I>(transformers).CanTransform<T>())
return std::get<I>(transformers).InTransform(in);
else
return in;
}

/// attempt to find transformer for this type
template<std::size_t I = 0, typename T>
inline typename std::enable_if < I != 0, T>::type TransformImpl(const T &in) const
{
if (std::get<I>(transformers).CanTransform<T>())
return std::get<I>(transformers).InTransform(in);
else
return TransformImpl<I - 1, T>(in);
}

std::tuple<const TRANSFORMERS...> transformers;
};


//Example usage

VariadicTransformer<MyTransformer, MyTransformer> varTrans;
MyPoint myPoint;
NotMyPoint notMyPoint;

std::cout << myPoint.x << std::endl;
myPoint = varTrans.Transform(myPoint);
std::cout << myPoint.x << std::endl;

std::cout << notMyPoint.x << std::endl;
notMyPoint = varTrans.Transform<NotMyPoint>(notMyPoint);
std::cout << notMyPoint.x << std::endl;

return 0;

我的问题来自这一行:

if constexpr(std::get<I>(transformers).CanTransform<T>())

这不会编译并提供以下错误:

error C2131: 表达式未计算为常量

注意:失败是由于读取超出其生命周期的变量导致的

注意:查看'this'的用法

CanTransform 函数应该是一个 constexpr,std::get<#>(std::tuple) 应该是一个 constexpr,所以我不确定它对这一行的提示是什么。

还需要 if constexpr 来避免尝试调用任何不符合转换当前类型条件的转换器,我希望这种情况失败并返回原始数据。

关于导致此错误的原因或我可以尝试的其他设计有什么建议吗?

最佳答案

如果调用对象也是constexpr,则对对象的方法调用将仅是constexpr。如果调用对象不是 constexpr,则该方法仍将在运行时而不是编译时进行计算,因此不符合任何编译时计算的条件。

struct A {
int val;
constexpr A() : A(16) {}
constexpr A(int val) : val(val) {}
constexpr bool foo() const {return val > 15;}
};

int main() {
A a;
if constexpr(a.foo()) {
std::cout << "No point thinking about it; this won't compile!" << std::endl;
} else {
std::cout << "Again, the previous line doesn't compile." << std::endl;
}

constexpr A b;
if constexpr(b.foo()) {
std::cout << "This, however, will compile, and this message will be displayed!" << std::endl;
}

constexpr A c(13);
if constexpr(c.foo()) {
std::cout << "This will not be displayed because the function will evaluate to false, but it will compile!" << std::endl;
}
}

需要保证TransformImpl可以constexpr,然后保证调用TransformImpl的A实例 也是 constexpr

关于C++17 if constexpr() 与元组一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47760029/

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