使用类型类使OpenGL的int常量类型安全

问题描述 投票:1回答:1

我想在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的常量?

scala opengl
1个回答
1
投票

根据经验,如果您不需要,请不要使用implicits。在这种情况下,您只需使用类型边界即可解决它:

// 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)
}

Try it out!

注意:如果你想创建更深层次的C继承结构,你可能想在GlConst中添加GlConstCap的逆变。


我希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.