如果原始源代码行无法编译,是否可以让模板选择备用源代码行?
我正在寻找一个相对通用的:
- 尝试编译这行代码,
- 如果成功,则编译并使用该行代码。否则
- 使用其他一些代码行
我有一个情况,我想根据提供的函子在 double 上是否有效来选择性地编译某些内容:
//Some user supplied functor I can't modify which works on `int` but not `double`
template<typename T>
struct LShift : std::binary_function<T, T, T>
{
T operator()(T lhs, T rhs)
{
return lhs << rhs;
}
};
//Class that holds either an int or a double
class Example
{
union
{
int intVal;
double dblVal;
} value;
bool isIntType;
public:
Example(int val)
: isIntType(true)
{
value.intVal = val;
}
Example(double val)
: isIntType(false)
{
value.dblVal = val;
}
int GetIntergalValue() const
{
return value.intVal;
}
double GetDoubleValue() const
{
return value.dblVal;
}
bool IsIntegral() const
{
return isIntType;
}
};
//Does something with an example. I know that if the examples have `double` contents,
//that the functor passed will also be valid for double arguments.
template <template <typename Ty> class FunctorT>
Example DoSomething(const Example& lhs, const Example& rhs)
{
if (lhs.IsIntergal() != rhs.IsIntergal())
{
throw std::logic_error("...");
}
if (lhs.IsIntegral())
{
return Example(FunctorT<int>(lhs.GetIntergalValue(), rhs.GetIntergalValue()));
}
else
{
return Example(FunctorT<double>(lhs.GetDoubleValue(), rhs.GetDoubleValue()));
}
}
int main()
{
DoSomething<LShift>();
}
我以前从未使用过 SFINAE,但是这是我的第一次尝试:
template <template <typename Ty> class FunctorT>
double DoDouble(double lhs, double rhs)
{
return FunctorT<double>()(lhs, rhs);
}
template <template <typename Ty> class FunctorT>
double DoDouble(int lhs, int rhs)
{
throw std::logic_error("That is not valid on floating types.");
}
我认为替换会在第一次重载时失败(将选择该重载,因为传递双精度数时这是一个更好的重载),然后该控制将继续进行第二次重载。然而,无论如何,整个事情都无法编译。
我想做的事情合理或可能吗?
I'm looking for a relatively generic:
- try to compile this line of code
- if that succeeds, compile and use that line of code. Otherwise
- use some other line of code
I've got a case where I'd like to selectively compile something based on whether the supplied functor is valid on double
s:
//Some user supplied functor I can't modify which works on `int` but not `double`
template<typename T>
struct LShift : std::binary_function<T, T, T>
{
T operator()(T lhs, T rhs)
{
return lhs << rhs;
}
};
//Class that holds either an int or a double
class Example
{
union
{
int intVal;
double dblVal;
} value;
bool isIntType;
public:
Example(int val)
: isIntType(true)
{
value.intVal = val;
}
Example(double val)
: isIntType(false)
{
value.dblVal = val;
}
int GetIntergalValue() const
{
return value.intVal;
}
double GetDoubleValue() const
{
return value.dblVal;
}
bool IsIntegral() const
{
return isIntType;
}
};
//Does something with an example. I know that if the examples have `double` contents,
//that the functor passed will also be valid for double arguments.
template <template <typename Ty> class FunctorT>
Example DoSomething(const Example& lhs, const Example& rhs)
{
if (lhs.IsIntergal() != rhs.IsIntergal())
{
throw std::logic_error("...");
}
if (lhs.IsIntegral())
{
return Example(FunctorT<int>(lhs.GetIntergalValue(), rhs.GetIntergalValue()));
}
else
{
return Example(FunctorT<double>(lhs.GetDoubleValue(), rhs.GetDoubleValue()));
}
}
int main()
{
DoSomething<LShift>();
}
I've never used SFINAE before, but this was my first attempt:
template <template <typename Ty> class FunctorT>
double DoDouble(double lhs, double rhs)
{
return FunctorT<double>()(lhs, rhs);
}
template <template <typename Ty> class FunctorT>
double DoDouble(int lhs, int rhs)
{
throw std::logic_error("That is not valid on floating types.");
}
I thought substitution would fail on the first overload (which would be selected because it's a better overload when passed doubles), and that control would then proceed to the second overload. However, the whole thing fails to compile anyway.
Is what I'm trying to do reasonable or possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
试试这个(它是即兴的,可能有语法错误):
或者您可以通过 Boost
enable_if
使用 SFINAE。但有一股浓烈的气味。未调用专业化的代码(!)很可能应该被重构。在某种程度上。
干杯&呵呵,
Try this (it's off the cuff, may have syntax erors):
Alternatively you can use SFINAE via Boost
enable_if
.But there is a strong smell about it. The code where the specialization is not invoked (!) should most probably be refactored. In some way.
Cheers & hth.,