【发布时间】:2018-10-08 08:20:09
【问题描述】:
假设你有几个类,它们都包含一个含义相同的静态变量,但不同类的名称不同。
一个玩具例子:
class Point2D
{
public:
static constexpr int dimension = 2;
private:
double x, y;
}
class Point3D
{
public:
static constexpr int dim = 3;
private:
double x, y, z;
};
我想用std::integral_constant 的孩子包装一个“维度”变量。请注意,我无法编辑“Point”类,因为它们是某些外部库的一部分。这个实现对我有用,但看起来很笨拙(我使用的是 VS2017):
template <typename T, typename = void>
struct HasDimensionVar : std::false_type { };
template <typename T>
struct HasDimensionVar<T, decltype( T::dimension, void( ) )> : std::true_type { };
template <typename T, typename = void>
struct HasDimVar : std::false_type { };
template <typename T>
struct HasDimVar<T, decltype( T::dim, void( ) )> : std::true_type { };
template <typename T, class Enable = void>
struct Dimension;
template <typename T>
struct Dimension<T, std::enable_if_t< HasDimensionVar<T>::value> > :
std::integral_constant<decltype( T::dimension ), T::dimension> { };
template <typename T>
struct Dimension<T, std::enable_if_t< HasDimVar<T>::value> > :
std::integral_constant<decltype( T::dim ), T::dim> { };
有没有办法跳过所有这些HasSomeVars 并像这样简短而清晰:
template <typename T, class Enable = void>
struct Dimension;
template <typename T>
struct Dimension<T, decltype( T::dimension, void( ) ) > :
std::integral_constant<decltype( T::dimension ), T::dimension> { };
template <typename T>
struct Dimension<T, decltype( T::dim, void( ) ) > :
std::integral_constant<decltype( T::dim ), T::dim> { };
此代码出现编译错误:
错误 C2953: 'Dimension': 类模板已定义
【问题讨论】:
-
似乎是a known problem,在 MSVC 中使用表达式 SFINAE 实现。
-
@IgorTandetnik,所以我最后的代码 sn-p 是正确的,但由于 MSVC 内部问题而无法编译?
-
这听起来真的很像XY problem。你想让我做什么?如果您只想检索值,则通过模板专业化间接获取
-
@PasserBy 哦,天哪,我尽量不要用额外的信息来使我的问题超载。:) 我想实现一个适用于许多不同类型“点”(内部和外部)的类。我需要在编译时获得“维度”值。但是我想释放用户为常见的“点”类型设置尺寸(例如,使用模板参数)(尽管如此,他需要为其他类型设置它)。 'Dimension' 包装器来了。我想平滑我的解决方案。您认为应该在我的问题中添加什么内容?
-
@PasserBy,我再次浏览了您的链接和我当前的解决方案。不,我不认为存在 XY 问题,因为我在这里唯一想知道 Has...Var 是否可以省略,它们看起来是不必要的。让我们认为给定的代码段周围没有其他任何东西。我只想知道我是否错过了更简洁的实现。
标签: c++ templates c++14 template-meta-programming sfinae