如今,Erwin Unruh工作的例子
Does example of Erwin Unruh work today?
这是Erwin Unruh
的示例,以使用C++
模板元编程来生成编译器错误消息中的质量数字。
// Erwin Unruh, untitled program,
// ANSI X3J16-94-0075/ISO WG21-462, 1994.
template <int i>
struct D
{
D(void *);
operator int();
};
template <int p, int i>
struct is_prime
{
enum { prim = (p%i) && is_prime<(i>2?p:0), i>::prim };
};
template <int i>
struct Prime_print
{
Prime_print<i-1> a;
enum { prim = is_prime<i,i-1>::prim };
void f() { D<i> d = prim; }
};
struct is_prime<0,0> { enum { prim = 1 }; };
struct is_prime<0,1> { enum { prim = 1 }; };
struct Prime_print<2>
{
enum { prim = 1 };
void f() { D<2> d = prim; }
};
void foo()
{
Prime_print<10> a;
}
预计结果将是此编译器错误消息:
// output:
// unruh.cpp 30: conversion from enum to D<2> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<3> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<5> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<7> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<11> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<13> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<17> requested in Prime_print
// unruh.cpp 30: conversion from enum to D<19> requested in Prime_print
我检查了此代码,并通过g++
进行了编译,但没有得到相同的结果。
尽管我通过
使用了c++17
g++ -std=c++17 -O3 main.cpp
看来,即使c++03
也无法正常工作。结果与预期无关。我应该使用不同的编译器选项吗?
main.cpp:25:1: error: an explicit specialization must be preceded by ‘template <>’
struct is_prime<0,0> { enum { prim = 1 }; };
^~~~~~~~~~~~~~~~~~~~
template <>
main.cpp:26:1: error: an explicit specialization must be preceded by ‘template <>’
struct is_prime<0,1> { enum { prim = 1 }; };
^~~~~~~~~~~~~~~~~~~~
template <>
main.cpp:27:1: error: an explicit specialization must be preceded by ‘template <>’
struct Prime_print<2>
^~~~~~~~~~~~~~~~~~~~~
template <>
main.cpp: In member function ‘void Prime_print<2>::f()’:
main.cpp:30:25: error: conversion from ‘Prime_print<2>::<unnamed enum>’ to non-scalar type ‘D<2>’ requested
void f() { D<2> d = prim; }
^~~~
main.cpp: In instantiation of ‘struct is_prime<0, 2>’:
main.cpp:14:25: required from ‘struct is_prime<3, 2>’
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<0, 2>’ used in nested name specifier
enum { prim = (p%i) && is_prime<(i>2?p:0), i>::prim };
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp: In instantiation of ‘struct is_prime<4, 3>’:
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<4, 3>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<5, 4>’:
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<5, 4>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<6, 5>’:
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<6, 5>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<7, 6>’:
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<7, 6>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<8, 7>’:
main.cpp:20:25: recursively required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<8, 7>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<9, 8>’:
main.cpp:21:10: required from ‘struct Prime_print<9>’
main.cpp:20:25: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<9, 8>’ used in nested name specifier
main.cpp: In instantiation of ‘struct is_prime<10, 9>’:
main.cpp:21:10: required from ‘struct Prime_print<10>’
main.cpp:35:21: required from here
main.cpp:14:25: error: incomplete type ‘is_prime<10, 9>’ used in nested name specifier
更新1
有一个替代代码,如用户Tony Delroy
所建议。我尝试了此代码,也没有用。
template <int i>
struct D
{
D(void *);
operator int();
};
template <int p, int i>
struct is_prime
{
enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0), i-1>::prim };
};
template <int i>
struct Prime_print
{
Prime_print<i-1> a;
enum { prim = is_prime<i,i-1>::prim };
void f() { D<i> d = prim ? 1 : 0; a.f(); }
};
struct is_prime<0,0> { enum { prim = 1 }; };
struct is_prime<0,1> { enum { prim = 1 }; };
struct Prime_print<2>
{
enum { prim = 0 };
void f() { D<1> d = prim? 1 : 0; }
};
int main()
{
Prime_print<18> a;
a.f()
}
更新2
我在这里找到了一个工作代码。唯一的问题是应该用grep
级联以给出结果
g++ -std=c++03 -c -fpermissive main.cpp 2>&1 | grep "In instantiation"
输出:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 17]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 13]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 11]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 7]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 5]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 3]’:
main.cpp: In instantiation of ‘void Prime_print<i>::f() [with int i = 2]’:
是否有任何方法可以在不使用Linux grep
命令的情况下产生单线错误?
/*
Prime number computation by Erwin Unruh
http://www.erwin-unruh.de/Prim.html
compatible with (now!) "valid" C++
compile --> the error messages are the prime numbers up to 18!
for clang: c++ unruh_new.cpp 2>&1 | grep -i error
for gnu: g++-mp-5 -std=c++03 -c
-fpermissive
unruh_new.cpp 2>&1 | grep "In instantiation"
*/
template <int i> struct D { D(void*); operator int(); };
template <int p, int i> struct is_prime {
enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0), i-1> :: prim };
};
template <int i> struct Prime_print {
Prime_print<i-1> a;
enum { prim = is_prime<i, i-1>::prim };
void f() { D<i> d = prim ? 1 : 0; a.f();}
};
template<> struct is_prime<0,0> { enum {prim=1}; };
template<> struct is_prime<0,1> { enum {prim=1}; };
template<> struct Prime_print<1> {
enum {prim=0};
void f() { D<1> d = prim ? 1 : 0; };
};
#ifndef LAST
#define LAST 18
#endif
main() {
Prime_print<LAST> a;
a.f();
}
下面您会发现我在C 讲座中使用的更新程序。它运行良好(即,它会产生错误;-)(即使使用G -8 -STD = C 2A。为了尝试一下,我建议使用以下脚本:w/o参数,您会得到素数直到25,使用数字参数(例如100(,您将获得Primes,直到100。。如果您想要所有编译器的输出提供任何第二个参数。
这是脚本:
#!/bin/bash
if [ $# -eq 0 ] ; then
last=25
else
last=$1
fi
if [ $# -gt 1 ] ; then
g++ --std=c++2a -DLAST=${last} primefrank.cc |& less
else
(g++ --std=c++2a -DLAST=${last} primefrank.cc 2>&1) |
grep 'instantiation of' |
sed 's/ instantiation of//'
fi
这是Prorgram的来源:
#ifndef LAST
#define LAST 18
#endif
enum
{
IS_PRIME,
NO_PRIME,
CONTINUE
};
template <int candidate, int testValue>
struct Eval
{
enum
{
mode =
testValue * testValue > candidate ? IS_PRIME :
candidate % testValue == 0 ? NO_PRIME :
CONTINUE
};
};
template <int candidate, int prime, int mode >
struct sieve
{
enum
{
next = prime + 1,
isPrime = sieve<candidate, next,
Eval<candidate, next>::mode>::isPrime
};
};
template <int candidate, int prime>
struct sieve<candidate, prime, IS_PRIME>
{
enum { isPrime = IS_PRIME };
};
template <int candidate, int prime>
struct sieve<candidate, prime, NO_PRIME >
{
enum { isPrime = NO_PRIME };
};
template <int prime>
struct test
{
enum {isPrime = sieve<prime, 2, Eval<prime, 2>::mode>::isPrime };
};
template <int prime, int isPrime>
struct show
{
static void f()
{
show<prime - 1, test<prime - 1>::isPrime >::f();
}
};
template <int prime>
struct show<prime, IS_PRIME>
{
static int *f()
{
show<prime - 1, test<prime - 1>::isPrime >::f();
int x;
return &x;
}
};
template <>
struct show<1, IS_PRIME>
{
static void f()
{}
};
template <int prime>
void primes()
{
show<prime, test<prime>::isPrime>::f();
}
int main()
{
// 'instantiation' messages because of the suggested grep command
static_assert(LAST >= 2,
"instantiation of LAST must be >= 2");
primes<LAST>();
static_assert(0,
"instantiation of compilation terminated");
}
在线搜索,《发现现代C 的书》的预览列出了struct is_prime
中的源代码略有不同:
enum { prim = (p == 2) || (p%i) etc...
下一页列出了很多错误,例如您记录的错误,并且在显示的编译器输出之后的页面更简洁地列出了素数:
error: initializing argument 1 of ...whatever... [ with int i = 17 ]
error: initializing argument 1 of ...whatever... [ with int i = 13 ]
...and so on...
所以 - 我建议您更仔细地查看您的错误消息。尽管如此,如何报告错误取决于您的编译器,并且可以合法地随版本而变化,因此编译器不产生您的期望并不是错误的。
相关文章:
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 如今,Erwin Unruh工作的例子