멤버 변수에 std::enable_if 또는 유사한 메서드 사용 (Using std::enable_if or similar method on member variable)


문제 설명

멤버 변수에 std::enable_if 또는 유사한 메서드 사용 (Using std::enable_if or similar method on member variable)

현재 다음과 같은 사용자 정의 벡터 클래스가 있습니다.

template<int D, typename T = float>
class Vec
{
    private:

        T data[D];

    public:

        Vec(T initial = 0)
        {
            for (int i = 0; i < D; ++i)
            {
                data[i] = initial;
            }
        }

        // Misc. operator overloads
};

using Vec2 = Vec<2>;
using Vec3 = Vec<3>;
using Vec4 = Vec<4>;

몇 가지 멤버 변수, 즉 x, y를 추가하고 싶습니다. zw 는 각각 벡터의 첫 번째, 두 번째, 세 번째 및 네 번째 위치를 가리킵니다. 이상적으로는 벡터가 충분한 차원으로 선언된 경우에만 이러한 변수가 표시됩니다. 즉, 2D 벡터는 Vec::z에 액세스할 수 없습니다.

제가 확인한 결과:

template<int D2 = D, typename  T2 = typename std::enable_if<(D2 > 0), T*>::type>
T2 x(){ return &data[0];}
template<int D2 = D, typename  T2 = typename std::enable_if<(D2 > 1), T*>::type>
T2 y(){ return &data[1];}
template<int D2 = D, typename  T2 = typename std::enable_if<(D2 > 2), T*>::type>
T2 z(){ return &data[2];}
template<int D2 = D, typename  T2 = typename std::enable_if<(D2 > 3), T*>::type>
T2 w(){ return &data[3];}

당신처럼 알 수 있듯이, 템플릿 매개변수 DT를 있는 그대로 입력하려고 하면 C++에 약간의 중년 위기가 오기 때문에 본질적으로 각각을 재정의해야 합니다. 그들을. 그리고 제가 말하려는 것이 터무니없지만 x, y, z에 대해 정말 말하고 싶습니다. 내 의견으로는 vec.xvec.x()보다 더 멋지게 보이기 때문입니다. >

변수에는 템플릿이 없고 클래스와 함수만 있기 때문에 이 솔루션을 사용할 수 없습니다. 제가 현재 가지고 있는 것은 다음과 같습니다.

typename std::conditional<(D > 0), T*, std::nullptr_t>::type x = &data[0];
typename std::conditional<(D > 1), T*, std::nullptr_t>::type y = &data[1];
typename std::conditional<(D > 2), T*, std::nullptr_t>::type z = &data[2];
typename std::conditional<(D > 3), T*, std::nullptr_t>::type w = &data[3];

플로트, 정수 등의 유형을 원했기 때문에 폴백 캐스트로 std::nullptr_t를 사용하기로 결정했습니다. 에 캐스팅할 수 없었습니다. 이것이 좋지 않다는 것을 알게 되었기 때문입니다. x, y, <이것은 여전히 4차원 미만의 class Vec 인스턴스에 대해 컴파일 오류를 발생시킵니다. 지금은 정말 혼란스럽습니다. 내가 얻는 오류는 cannot convert 'float*' to 'std::conditional::type' {aka 'std::nullptr_t} 의미가 없으면 getW()를 실행해서는 안 되며, float*std::nullptr_t를 비교해서는 안 됩니다. ..?


참조 솔루션

방법 1:

You need to specialize Vec to add these variables. Specializing the entire Vec class would result in a whole lot of duplicated code so you can hoist it into a base class responsible for storing the data of a vector.

template<size_t D, typename T>
class VecStorage {
  T data[D];

public:
  T &operator[](const size_t i) {
    return const_cast<T &>(std::as_const(*this)[i]);
  }
  const T &operator[](const size_t i) const {
    assert(i < D);
    return data[i];
  }
};

template<typename T>
class VecStorage<2, T> {
public:
  T x, y;

  T &operator[](const size_t i) {
    return const_cast<T &>(std::as_const(*this)[i]);
  }
  const T &operator[](const size_t i) const {
    assert(i < 2);
    if (i == 0) {
      return x;
    } else {
      return y;
    }
  }
};

I've specialized VecStorage for 2 dimensions. You can add specializations for 3 and 4 dimensions. Since VecStorage exposes the subscript operator, Vec and users of Vec can treat it like an array.

template<size_t D, typename T = float>
class Vec : public VecStorage<D, T> {
public:
  explicit Vec(T initial = 0) {
    for (size_t i = 0; i != D; ++i) {
      (*this)[i] = initial;
    }
  }
};

int main() {
  Vec<2> v{42};
  std::cout << v.x << ' ' << v.y << '\n'; // 42 42
  v[0] = 5;
  v[1] = 7;
  std::cout << v.x << ' ' << v.y << '\n'; // 5 7
}

(by 小奥利奥Indiana Kernick)

참조 문서

  1. Using std::enable_if or similar method on member variable (CC BY‑SA 2.5/3.0/4.0)

#C++ #sfinae #Variables






관련 질문

파일의 암호화/복호화? (Encryption/ Decryption of a file?)

이상한 범위 확인 연산자가 있는 C++ typedef (C++ typedef with strange scope resolution operator)

개체 배열 매개변수--오류: '문자' 필드에 불완전한 유형이 있습니다. (Object array parameter--error: field ‘letters’ has incomplete type)

C++에서 메모리 삭제 (Deleting memory in c++)

C++ 프로그램을 실행할 수 없습니다. No se ejecuta el programa (C++ i can't run a program. No se ejecuta el programa)

컴파일 시 변수의 이름과 수명 (Name and lifetime of variables at compile time)

control-c 후 Visual Studio 콘솔 프로그램 충돌 (visual studio console program crashes after control-c)

멤버 변수에 std::enable_if 또는 유사한 메서드 사용 (Using std::enable_if or similar method on member variable)

ifstream input_file(filename); (I am receiving an error "no matching function to call" in the line ifstream input_file(filename);)

ESP8266에서 잠시 실행하면 JsonData 크기가 0이 됩니다. (JsonData size becomes zero after awhile of running in ESP8266)

합에 대한 속도 문제(제수의 합) (Speed problem for summation (sum of divisors))

벡터 벡터에서 하위 벡터의 첫 번째 값을 찾기 위해 begin() 및 end() 반복기의 범위를 지정하는 방법은 무엇입니까? (How to specify a range for begin() and end() iterators to find first value of sub vector in a vector of vectors?)







코멘트