関数を定義する方法2006

  • ようやく関数の定義の仕方が分かってきたのでまとめておこう
  • Iterator AdaptorのためにFunctionObjectはできるだけDefaultConstructibleかつAssignableにしておいた方がいい
  • この不具合の回避策がかなり正確に分かった
    • 基底クラスを持つか、あるいはユーザ定義のコンストラクタが一つ必要、ということらしい
  • GCC3.4の場合、result_ofの話とは関係なく、型にDefaultConstructibleを要求するバグがある
  • 結局result_ofのカスタマイズはそのままでは使いづらいので、ドメインに応じたレイヤーを作ればよいと思う
  • AdaptableコンセプトはもうObsoleteだろう


[]#include[] []<boost/type_traits/decay.hpp>[]
[]#include[] []<boost/type_traits/remove_cv.hpp>[]
[]#include[] []<boost/type_traits/remove_reference.hpp>[]
[]#include[] []<boost/utility/result_of.hpp>[]
[]#include[] []<string>[]

[]// my.hpp[]
[]//[]

[]namespace[] []my[][] {[]


[]// ポリモーフィックでない場合[]

[]namespace[] []op[][] {[]

[]struct[] []less[]
[] {[]
[]typedef[] []bool[] []result_type[][];[]

[]template[][]< [][]class[] []A0[][], [][]class[] []A1[][] >[]
[]bool[] []operator[][]()([][]A0[] []a0[][], [][]A1[] []a1[][]) [][]const[]
[] {[]
[]return[] []a0[][] < [][]a1[][];[]
[] }[]
[] };[]

[] }[]

[]// 厳密にはODR違反になり得るが、実際に問題を起こすことはない(らしい)[]
[]op[][]::[][]less[] []const[] []less[][] = { };[]

[]// シングルトンでODR違反を回避する[]
[]template[][]< [][]class[] []T[][] >[]
[]struct[] []singleton[]
[] {[]
[]static[] []T[] []instance[][];[]
[] };[]

[]template[][]< [][]class[] []T[][] >[]
[]T[] []singleton[][]<[][]T[][]>::[][]instance[][];[]

[]namespace[][] {[]
[]op[][]::[][]less[] []const[][]& [][]less2[][] = [][]singleton[][]<[][]op[][]::[][]less[][]>::[][]instance[][];[]
[] }[]


[]// ポリモーフィックな場合[]

[]namespace[] []op[][] {[]

[]struct[] []identity[]
[] {[]
[]template[][]< [][]class[] []FunCall[][] >[]
[]struct[] []result[][];[]

[]template[][]< [][]class[] []Fun[][], [][]class[] []A[][] >[]
[]struct[] []result[][]<[][]Fun[][]([][]A[][])> :[]
[]boost[][]::[][]remove_cv[][]<[][]typename[] []boost[][]::[][]decay[][]<[][]A[][]>::[][]type[][]>[]
[] { };[]

[]template[][]< [][]class[] []A[][] >[]
[]A[] []operator[][]()([][]A[] []a[][]) [][]const[]
[] {[]
[]return[] []a[][];[]
[] }[]
[] };[]

[] }[]

[]op[][]::[][]identity[] []const[] []identity[][] = { };[]


[]// ポリモーフィックかつ引数の数がゼロになり得る場合[]

[]namespace[] []op[][] {[]

[]struct[] []zero[]
[] {[]
[]int[] []operator[][]()() [][]const[]
[] {[]
[]return[] []0[][];[]
[] }[]

[]template[][]< [][]class[] []FunCall[][] >[]
[]struct[] []result[][];[]

[]template[][]< [][]class[] []Fun[][] >[]
[]struct[] []result[][]<[][]Fun[][]([][]std[][]::[][]string[][]&)>[]
[] {[]
[]typedef[] []std[][]::[][]string[][]& [][]type[][];[]
[] };[]

[]std[][]::[][]string[][]& [][]operator[][]()([][]std[][]::[][]string[][]& [][]str[][]) [][]const[]
[] {[]
[]str[][] += [][]"0"[][];[]
[]return[] []str[][];[]
[] }[]
[] };[]

[] }[]

[]op[][]::[][]zero[] []const[] []zero[][] = { };[]

[]} [][]// namespace my[]

[]namespace[] []boost[][] {[]

[]template[][]< >[]
[]struct[] []result_of[][]<[][]my[][]::[][]op[][]::[][]zero[][]()>[]
[] {[]
[]typedef[] []int[] []type[][];[]
[] };[]

[]template[][]< >[]
[]struct[] []result_of[][]<[][]my[][]::[][]op[][]::[][]zero[] []const[][]()>[]
[] {[]
[]typedef[] []int[] []type[][];[]
[] };[]

[]} [][]// namespace boost[]


[]namespace[] []my[][] {[]


[]// VC++7.1/8のバグについて[]

[]namespace[] []op[][] {[]

[]template[][]< [][]class[] []T[][] >[]
[]struct[] []foo_error[]
[] {[]
[]template[][]< [][]class[] []FunCall[][] >[]
[]struct[] []result[][];[]

[]template[][]< [][]class[] []Fun[][], [][]class[] []A[][] >[]
[]struct[] []result[][]<[][]Fun[][]([][]A[][])>[]
[] {[]
[]typedef[] []int[] []type[][];[]
[] };[]

[]int[] []operator[][]()([][]int[] []a[][]) [][]const[]
[] {[]
[]return[] []a[][];[]
[] }[]
[] };[]

[]template[][]< [][]class[] []T[][] >[]
[]struct[] []foo_ok[]
[] {[]
[]template[][]< [][]class[] []FunCall[][] >[]
[]struct[] []result[][];[]

[]template[][]< [][]class[] []Fun[][], [][]class[] []A[][] >[]
[]struct[] []result[][]<[][]Fun[][]([][]A[][])>[]
[] {[]
[]typedef[] []int[] []type[][];[]
[] };[]

[]int[] []operator[][]()([][]int[] []a[][]) [][]const[]
[] {[]
[]return[] []a[][];[]
[] }[]

[]#if[][] defined(BOOST_MSVC)[]
[]// ユーザ定義のコンストラクタが一個必要[]
[]foo_ok[][]() { }[]
[]#endif[]
[] };[]

[]struct[] []dummy[][] { };[]

[]template[][]< [][]class[] []T[][] >[]
[]struct[] []foo_ok2[]
[]#if[][] defined(BOOST_MSVC)[]
[]// 基底クラスも持つのもよい[]
[] : [][]dummy[]
[]#endif[]
[] {[]
[]template[][]< [][]class[] []FunCall[][] >[]
[]struct[] []result[][];[]

[]template[][]< [][]class[] []Fun[][], [][]class[] []A[][] >[]
[]struct[] []result[][]<[][]Fun[][]([][]A[][])>[]
[] {[]
[]typedef[] []int[] []type[][];[]
[] };[]

[]int[] []operator[][]()([][]int[] []a[][]) [][]const[]
[] {[]
[]return[] []a[][];[]
[] }[]
[] };[]

[] } [][]// namespace op[]


[]} [][]// namespace my[]


[]// my_test.cpp[]
[]//[]

[]void[] []test[][]()[]
[]{[]
[] {[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]less[][]([][]int[][], [][]int[][])>::[][]type[] []a[][] = [][]my[][]::[][]less[][]([][]10[][], [][]12[][]);[]
[]BOOST_CHECK[][]([][]a[][] == [][]true[][]);[]
[] }[]
[] {[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]less[][]([][]int[][], [][]int[][])>::[][]type[] []a[][] = [][]my[][]::[][]less2[][]([][]12[][], [][]10[][]);[]
[]BOOST_CHECK[][]([][]a[][] == [][]false[][]);[]
[] }[]
[] {[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]zero[][]()>::[][]type[] []a[][] = [][]my[][]::[][]zero[][]();[]
[]BOOST_CHECK[][]([][]a[][] == [][]0[][]);[]
[]std[][]::[][]string[] []str[][]([][]"zero is "[][]);[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]zero[][]([][]std[][]::[][]string[][]&)>::[][]type[] []b[][] = [][]my[][]::[][]zero[][]([][]str[][]);[]
[]BOOST_CHECK[][]([][]b[][] == [][]"zero is 0"[][]);[]
[] }[]
[] {[]
[]//boost::result_of<my::op::foo_error<int>(int)>::type error;[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]foo_ok[][]<[][]int[][]>([][]int[][])>::[][]type[] []ok[][];[]
[]boost[][]::[][]result_of[][]<[][]my[][]::[][]op[][]::[][]foo_ok2[][]<[][]int[][]>([][]int[][])>::[][]type[] []ok2[][];[]
[] }[]
[]}[]


[]int[] []test_main[][]([][]int[][], [][]char[][]*[])[]
[]{[]
[] ::[][]test[][]();[]
[]return[] []0[][];[]
[]}[]