c ++:从模板参数生成字符串文字 [英] c++: generating string literals from template parameters
本文介绍了c ++:从模板参数生成字符串文字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
template < unsigned int i >
struct t {
static const char *s;
};
template < unsigned int i >
const char* t<i>::s = ...;
其中 ...
为0 1 2 ... i-1,例如0 1 2 3 4for i == 5
。
where ...
is "0 1 2 ... i-1", for example "0 1 2 3 4" for i == 5
.
这是可能吗? (没有解决方案这样做在运行时,请!)
Is this possible? (no solutions doing this at run-time, please!)
- 问题的好奇心(做预处理器宏/常量容易,但是如何模板参数)?
- 含义是:编译时生成的字符串文字。我现在看到
const
不强制这样做,但可以采用任何运行时评估函数来生成字符串。
- Question asked out of curiosity (doing it with preprocessor macros / constants would be easy, but how about template parameters)?
- The meaning is: compile-time generated string literal. I see now that
const
does not force this, but could take any run-time evaluated function for string generation.
推荐答案
这在技术上是可能的,它只是非常丑陋。下面是一个为unsigned int生成字符串文本的示例。它没有(还)创建一个形式为1 2 3 ... i-1的字符串,但我相信如果你愿意花费的努力是可能的。
This is technically possible, it's just very very ugly. Here's a sample that generates a string literal for an unsigned int. It does not (yet) create a string of the form "1 2 3 ... i-1", however I'm sure it is possible if you're willing to spend the effort.
#include <iostream>
#include <string>
#include <limits>
///////////////////////////////////////////////////////////////////////////////
// exponentiation calculations
template <int accum, int base, int exp> struct POWER_CORE : POWER_CORE<accum * base, base, exp - 1>{};
template <int accum, int base>
struct POWER_CORE<accum, base, 0>
{
enum : int { val = accum };
};
template <int base, int exp> struct POWER : POWER_CORE<1, base, exp>{};
///////////////////////////////////////////////////////////////////////////////
// # of digit calculations
template <int depth, unsigned int i> struct NUM_DIGITS_CORE : NUM_DIGITS_CORE<depth + 1, i / 10>{};
template <int depth>
struct NUM_DIGITS_CORE<depth, 0>
{
enum : int { val = depth};
};
template <int i> struct NUM_DIGITS : NUM_DIGITS_CORE<0, i>{};
template <>
struct NUM_DIGITS<0>
{
enum : int { val = 1 };
};
///////////////////////////////////////////////////////////////////////////////
// Convert digit to character (1 -> '1')
template <int i>
struct DIGIT_TO_CHAR
{
enum : char{ val = i + 48 };
};
///////////////////////////////////////////////////////////////////////////////
// Find the digit at a given offset into a number of the form 0000000017
template <unsigned int i, int place> // place -> [0 .. 10]
struct DIGIT_AT
{
enum : char{ val = (i / POWER<10, place>::val) % 10 };
};
struct NULL_CHAR
{
enum : char{ val = '\0' };
};
///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '0000000017' to a character
template <unsigned int i, int place> // place -> [0 .. 9]
struct ALT_CHAR : DIGIT_TO_CHAR< DIGIT_AT<i, place>::val >{};
///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '17' to a character
// Template description, with specialization to generate null characters for out of range offsets
template <unsigned int i, int offset, int numDigits, bool inRange>
struct OFFSET_CHAR_CORE_CHECKED{};
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, false> : NULL_CHAR{};
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, true> : ALT_CHAR<i, (numDigits - offset) - 1 >{};
// Perform the range check and pass it on
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE : OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, offset < numDigits>{};
// Calc the number of digits and pass it on
template <unsigned int i, int offset>
struct OFFSET_CHAR : OFFSET_CHAR_CORE<i, offset, NUM_DIGITS<i>::val>{};
///////////////////////////////////////////////////////////////////////////////
// Integer to char* template. Works on unsigned ints.
template <unsigned int i>
struct IntToStr
{
const static char str[];
};
template <unsigned int i>
const char IntToStr<i>::str[] =
{
OFFSET_CHAR<i, 0>::val,
OFFSET_CHAR<i, 1>::val,
OFFSET_CHAR<i, 2>::val,
OFFSET_CHAR<i, 3>::val,
OFFSET_CHAR<i, 4>::val,
OFFSET_CHAR<i, 5>::val,
OFFSET_CHAR<i, 6>::val,
OFFSET_CHAR<i, 7>::val,
OFFSET_CHAR<i, 8>::val,
OFFSET_CHAR<i, 9>::val,
NULL_CHAR::val
};
///////////////////////////////////////////////////////////////////////////////
// Tests
int _tmain(int argc, _TCHAR* argv[])
{
std::wcout << IntToStr<17>::str << std::endl;
std::wcout << IntToStr<173457>::str << std::endl;
std::wcout << IntToStr< INT_MAX >::str << std::endl;
std::wcout << IntToStr<0>::str << std::endl;
std::wcout << IntToStr<1>::str << std::endl;
std::wcout << IntToStr<-1>::str << std::endl;
return 0;
}
这篇关于c ++:从模板参数生成字符串文字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文