12

我在 GCC 4.3.2 的 C++11 的半实现中使用 TMP,我想知道是否有办法以某种方式执行以下操作:

template <char x, char... c>
struct mystruct {
...
};

int main () {

   mystruct<"asdf">::go();

}

它显然不会让我那样做,而且我认为在编译时使用用户定义的文字来转换“asdf”字符串会很幸运,但是 GCC 4.3 不支持用户定义的文字...

有什么建议么?我宁愿不做'a','s','d','f',因为这严重阻碍了我对这个项目的计划。

4

9 回答 9

10

我解决了一个类似的问题。我们需要为每个名称使用不同的类型

template< const char* the_name >
class A
{
    public:
    const char* name( void )
    {
        return the_name;
    }
};

extern const char g_unique_name[]; // defined elsewhere
typedef A<g_unique_name> A_unique;

这将使您在编译时访问名称和唯一的实例化。但是,它不会让您在运行时访问单个字符。

如果您想要单个字符访问,实现它的唯一方法是使用用户定义的文字。C++0x 将被扩展以允许上面的 main 函数中的语法,但它仍会将模板绑定到字符指针而不是编译时字符数组。

于 2009-04-03T00:37:21.360 回答
9

可悲的是,您仍然必须将其拆分为单独的字符,例如:

myTemplate<'s','t','r','i','n','g'>

在我看来,这是对新标准的巨大疏忽。其他一些人同意了,并尝试在 GCC 中实现该行为,并取得了不错的效果。你可以在这里找到那个线程。

编辑:链接有一些奇怪的问题,所以从这里剪切和粘贴:

http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/9b0edd169ba2ce3c

于 2009-04-03T01:10:59.547 回答
3

试试这个:

extern const char SOMESTRING[] = "stringhere"; //extern linkage required!

template<const char * const STR>
struct MyStruct
{
  static std::string doThis() { return STR; }
};



MyStruct<SOMESTRING>   testObj; //ok!

克里斯

于 2009-04-20T10:27:04.827 回答
3

最近在 Boost.MPL 中添加了一个“字符串”,允许编写:

typedef mpl::string<'asdf'> asdf;
typedef mpl::push_back<asdf, mpl::char_<'!'> >::type asdf_bang;

BOOST_ASSERT(0 == std::strcmp(mpl::c_str<asdf_bang>::value, "asdf!"));

请注意,上面显示的示例有点做作,因为必须拆分由超过 4 个字符组成的“字符串”。例如:

typedef mpl::string<'hell','o wo','rld'> hello;
于 2009-10-22T17:21:36.287 回答
2

在 C++11 中,无法在编译时将临时字符串存储在任何地方。所以我可以建议你这种方法:(这是快速制作的草图,但描述性很好)

#include <stdio.h>

template <char...>
struct StringTuple;

template <char TargHead>
struct StringTuple<TargHead> {
    static constexpr char kSymbol = TargHead;

    static void print() {
        printf(kSymbol ? "%c\n" : "\n", kSymbol);
    }
};

template <char TargHead, char... TargTail>
struct StringTuple<TargHead, TargTail...> {
    using Next = StringTuple<TargTail...>;
    static constexpr char kSymbol = TargHead;

    static void print() {
        if (kSymbol) {
            printf("%c", kSymbol);
            Next::print();
        } else {
            printf("\n");
        }
    }
};

constexpr int length(char *string) {
    return (string[0] == 0) ? 1 : (length(string + 1) + 1);
}

constexpr char get(char *string, int i) {
    return i < length(string) ? string[i] : 0;
}

#define ST(string) \
    StringTuple< \
    get(string, 0), \
    get(string, 1), \
    get(string, 2), \
    get(string, 3), \
    get(string, 4), \
    get(string, 5), \
    get(string, 6), \
    get(string, 7), \
    get(string, 8), \
    get(string, 9), \
    get(string, 10), \
    get(string, 11), \
    get(string, 12), \
    get(string, 13), \
    get(string, 14), \
    get(string, 15), \
    get(string, 16), \
    get(string, 17), \
    get(string, 18), \
    get(string, 19), \
    get(string, 20), \
    get(string, 21), \
    get(string, 22), \
    get(string, 23), \
    get(string, 24), \
    get(string, 25), \
    get(string, 26), \
    get(string, 27), \
    get(string, 28), \
    get(string, 29), \
    get(string, 30), \
    get(string, 31), \
    get(string, 32), \
    get(string, 33), \
    get(string, 34), \
    get(string, 35), \
    get(string, 36), \
    get(string, 37), \
    get(string, 38), \
    get(string, 39), \
    get(string, 40), \
    get(string, 41), \
    get(string, 42) \
    >

int main() {
    ST("Hello, compile-time world!")::print();
}

生成部分宏的 Bash 代码:

for i in `seq 0 42`; do echo "    get(string, $i), \\"; done

您必须将大量(1000 或更多)传递给此生成器以支持所有字符串,并且如果字符串超过此限制,您必须进行静态断言。


我在自己的科学项目中使用这种生成的宏。我知道这看起来很乱,但它确实有效。生成宏的使用示例:

#define PRINT(a) print(a);
FOREACH_MACRO(PRINT, a, b, c) // print(a);print(b);print(c);

我会尝试找到更漂亮的解决方案,但首先我会使用它。

于 2012-09-17T00:08:11.993 回答
0

我不确定您想要实现什么,但是当您将“asdf”传递给模板时,它的类型是 char *,值是字符串的地址。因此,像概述的那样简单的方法将失败。如果不知道您首先要解决什么问题,就很难推荐任何东西。

于 2009-04-02T22:12:12.457 回答
0

你不能那样做。从标准中的 14.3.2 开始:

非类型、非模板模板参数的模板参数应为以下之一:

  • 整数或枚举类型的整数常量表达式;或者
  • 非类型模板参数的名称;或者
  • 具有外部链接的对象或函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 & id-expression 其中 & 是可选的,如果名称指代
  • 一个函数或数组,或者如果相应的模板参数是一个引用;或者
  • 计算结果为空指针值的常量表达式(4.10);或者
  • 一个常量表达式,计算结果为空成员指针值 (4.11);或者
  • 指向成员的指针,如 5.3.1 中所述。
  • [注意:字符串文字(2.13.4)不满足任何这些类别的要求,因此不是可接受的模板参数
于 2009-04-02T22:21:54.167 回答
0

引用新标准草案:

14.3.2 模板非类型参数 [temp.arg.nontype]

2 注意:字符串文字 (2.13.4) 不满足任何这些类别的要求,因此不是可接受的模板参数。

例子:

template<class T, char* p>
class X 
{ 
X(); 
X(const char* q) { /... / } 
}; 

X<int, "Studebaker"> x1; // error: string literal as template-argument char p[] = "Vivisectionist";
X<int,p> x2; // OK

试试这个,但我不确定,因为http://gcc.gnu.org/gcc-4.3/cxx0x_status.html没有说明这个特性。

于 2009-04-02T22:23:23.647 回答
0

莫蒂错了。

不幸的是,当前标准 (C++11) 不支持字符串参数的可变模板文字运算符,它仅适用于数字。

template <char... Args>
operator ""_op();

...

1212_op; // legal, calls operator ""_op<'1','2','1','2'>;
"1212"_op; // illegal

我不明白这个限制的目的。

于 2012-09-16T23:41:15.983 回答