首页 > 解决方案 > 使用类型类使 OpenGL 的 int 常量类型安全

问题描述

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

标签: scalaopengl

解决方案


根据经验,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.GlConstGlConstCap


我希望这有帮助。


推荐阅读