Обеспечение безопасности констант int в OpenGL с использованием классов типов - PullRequest
1 голос
/ 07 марта 2019

Я пытаюсь создать безопасную оболочку вокруг lwjgl. Самое главное, я хочу, чтобы это была ошибка времени компиляции, чтобы передать неправильные константы в функцию, например звонит glEnable(GL_ARRAY_BUFFER). Это было бы довольно просто, если бы не разные контексты, поддерживающие разные константы для одной и той же функции.

Я подумал, что буду использовать классы типов для моделирования, какие константы могут быть переданы в какую функцию. У меня есть решение, но по общему признанию это немного уродливо и не может применить неявное:

trait GlConst { val glConst: Int }

trait GlConstCompanion[C <: GlConst] { val instance: C }


class GlDepthTest private () extends GlConst { val glConst = GL_DEPTH_TEST }

object GlDepthTest extends GlConstCompanion[GlDepthTest] {
  val instance = new GlDepthTest
}


class GlLineSmooth private () extends GlConst { val glConst = GL_LINE_SMOOTH }

object GlLineSmooth extends GlConstCompanion[GlLineSmooth] {
  val instance = new GlLineSmooth
}


class GlArrayBuffer private () extends GlConst { val glConst = GL_ARRAY_BUFFER }

object GlArrayBuffer extends GlConstCompanion[GlArrayBuffer] {
  val instance = new GlArrayBuffer
}


// type class for arguments to glEnable
trait GlEnableCap[T <: GlConst] extends GlConst


object GlContext33 {
  implicit object GlDepthTestIsEnableCap extends GlEnableCap[GlDepthTest] {
    val glConst = GlDepthTest.instance.glConst
  }

  implicit object GlLineSmoothIsEnableCap extends GlEnableCap[GlLineSmooth] {
    val glConst = GlLineSmooth.instance.glConst
  }

  def glEnable[T <: GlConst : GlEnableCap](t: T): Unit = println(implicitly[GlEnableCap[T]].glConst)
}

object Test extends App {
  import GlContext33._

  implicit def constComp2Const[C <: GlConst](cc: GlConstCompanion[C]): C = cc.instance

  // works
  glEnable(GlDepthTest.instance)

  // fails to apply implicit glConstComp2Comp
  glEnable(GlDepthTest)

  // fails intentionally
  glEnable(GlArrayBuffer)
}

Есть ли способ заставить неявное работать? Или есть еще лучший способ обернуть константы OpenGL?

1 Ответ

1 голос
/ 08 марта 2019

Как правило, не используйте implicit s, если не нужно. В этом случае вы также можете решить эту проблему, используя только границы типа:

// Start writing your ScalaFiddle code here

val GL_DEPTH_TEST = 1
val GL_LINE_SMOOTH = 1
val GL_ARRAY_BUFFER = 1


trait GlConstCap

trait GlEnableConstCap extends GlConstCap
trait GlBufferConstCap extends GlConstCap

trait GlConst[C <: GlConstCap] { val value: Int }

object GlDepthTest extends GlConst[GlEnableConstCap] {
  val value = GL_DEPTH_TEST
}

object GlLineSmooth extends GlConst[GlEnableConstCap] {
  val value = GL_LINE_SMOOTH
}

object GlArrayBuffer extends GlConst[GlBufferConstCap] {
  val value = GL_ARRAY_BUFFER
}


object GlContext33 {
  def glEnable[T <: GlConst[GlEnableConstCap]](t: T): Unit = println(t.value)
}

object Test extends App {
  import GlContext33._

  // works
  glEnable(GlDepthTest)

  // fails to apply implicit glConstComp2Comp
  glEnable(GlDepthTest)

  // fails intentionally
  glEnable(GlArrayBuffer)
}

Попробуйте!

Примечание. Возможно, вы захотите добавить контрастность к C в GlConst, если хотите создать более глубокие структуры наследования GlConstCap.


Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...