如何在C++中使用编译时三元运算符来获取对象成员
How to use compile-time ternary operator in C++ to get object member
我有一个模板化类eglue
,它根据传入的参数之一确定自己的n_rows和n_cols,保证具有n_rows和n_cols成员。代码如下:
template<typename> struct isEglueOrMat : std::false_type {};
template<typename T1, operations _op, typename T2> struct isEglueOrMat<eglue<T1, _op, T2>> : std::true_type {};
template<> struct isEglueOrMat<Matrix> : std::true_type {};
template<typename T1, operations _op, typename T2>
class eglue {
public:
const T1& First;
const T2& Second;
const unsigned n_rows;
const unsigned n_cols;
eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(isEglueOrMat<T1>()? f.n_rows:s.n_rows), n_cols(isEglueOrMat<T1>()? f.n_cols:s.n_cols) {}
这不起作用,失败并出现错误request for member 'n_rows' in 'f', which is of non-class type 'const float'
,当我只想从另一个项目获取n_rows
时,这将是一个eglue
或Matrix
的对象。
我尝试过的另一种方法是模板化构造函数:
template<typename Dummy = void, typename Dummy2 = std::enable_if_t<isEglueOrMat<T1>(), Dummy>> eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(f.n_rows), n_cols(f.n_cols) {}
template<typename Dummy = void, typename Dummy2 = std::enable_if_t<isEglueOrMat<T2>(), Dummy>> eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(s.n_rows), n_cols(s.n_cols) {}
此操作失败并显示错误
type/value mismatch at argument 1 in template parameter list for 'template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type'
template<typename Dummy = void, typename Dummy2 = std::enable_if_t<isEglueOrMat<T1>(), Dummy>> eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(f.n_rows), n_cols(f.n_cols) {}
^
error: expected a constant of type 'bool', got 'isEglueOrMat<T1>()'
即使我已经在代码的其他点成功使用了isEglueOrMat<type>()
(如有必要,我会发布这些内容,但我已经看到它在其他情况下有效)。
我知道这可能是重复的或类似于其他问题,但我真的无法让它工作......任何建议将不胜感激。
编辑:我是个白痴,第二种方法无论如何都行不通,因为你不能用相同的签名重载构造函数...... 有没有办法使第一种方法(或任何其他方法!)起作用?
您可以将标记调度与委派构造函数一起使用:
template<typename T1, operations _op, typename T2>
class eglue {
public:
const T1& First;
const T2& Second;
const unsigned n_rows;
const unsigned n_cols;
eglue(const T1& f, const T2& s) : eglue(f,s,isEglueOrMat<T1>()) {}
private:
eglue(const T1& f, const T2& s, std::true_type) : First(f), Second(s), n_rows(f.n_rows), n_cols(f.n_cols) {}
eglue(const T1& f, const T2& s, std::false_type) : First(f), Second(s), n_rows(s.n_rows), n_cols(s.n_cols) {}
};
或者第二种方法,确保间接依赖于T1
:
template<typename T1, operations _op, typename T2>
class eglue {
public:
const T1& First;
const T2& Second;
const unsigned n_rows;
const unsigned n_cols;
template <typename _T1 = T1, std::enable_if_t<isEglueOrMat<_T1>{}, bool> = true>
eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(f.n_rows), n_cols(f.n_cols) {}
template <typename _T1 = T1, std::enable_if_t<!isEglueOrMat<_T1>{}, bool> = false>
eglue(const T1& f, const T2& s) : First(f), Second(s), n_rows(s.n_rows), n_cols(s.n_cols) {}
};
对于第二种工作方法,您应该使用isEglueOrMat<T>::value
作为布尔常量。当你使用isEglueOrMat<T>()
时,它被视为类型为integral_constant
的对象,一个结构。当你在其他布尔表达式中使用它时,它被静默地强制为 bool(std::integral_constant
确实提供了这样的运算符)。另一种选择是将其显式转换为布尔值,static_cast<bool>(isEglueOrMat<T>())
也有效,C 样式的强制转换也是如此。
第一种方法也可以变得可行,但它需要更多的间接性(普通的标准运算符不会像你看到的那样工作)和一些乍一看很棘手的 SFINAE 游戏。
- 三元运算符和 if constexpr
- 在 c++ 中三元运算符中不允许继续(关键字)吗?
- 三元运算符在返回语句中给出意外的结果
- 递归中三元运算符的奇怪行为
- 错误:三元运算符无法在对象中正常工作"cout"
- 是否允许三元运算符在C++中计算两个操作数?
- 有条件地选择带有 decltype() 和三元运算符的类型
- 三元运算符在C++中的意外行为
- 有没有办法将 for 循环结果返回到像三元运算符这样的函数中?
- 变量值,在三元运算符之后
- 是否可以在C++中使用三元运算符在 if 语句中选择比较运算符?
- c++中的增量和三元运算符优先级
- C++中三元运算符的意外行为
- 用于返回开关的三元运算符
- 替换模板元编程中的三元运算符
- 三元运算符 '?:' 在 4.9.0 之前的 GCC 版本中推断出不正确的类型?
- 在 std::map 上使用三元运算符和 std::更大的附加参数
- "Do nothing"在三元运算符的其他部分?
- 如何确定三元运算符的返回类型?
- 无法使用三元运算符有条件地分配"istream &"?