将字符串文字作为参数传递给 C++ 模板类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2033110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:53:34  来源:igfitidea点击:

Passing a string literal as a parameter to a C++ template class

c++templates

提问by Mawg says reinstate Monica

I want a class which takes two parameters in its constructor. The first can be either an int, double or float, so <typename T>, and the second is always a string literal "my string", so I guess const char * const.

我想要一个在其构造函数中带有两个参数的类。第一个可以是 int、double 或 float,所以<typename T>,第二个总是字符串文字“我的字符串”,所以我猜const char * const.

Can anyone give me some compilable code which declares a simple class template as described and declares an object of that class?

谁能给我一些可编译的代码,它声明一个简单的类模板,并声明该类的一个对象?

Thanks

谢谢

采纳答案by Mooing Duck

Sorry, C++ does not currently support the use of string literals (or real literals) as template parameters.

抱歉,C++ 目前不支持使用字符串文字(或真实文字)作为模板参数。

But re-reading your question, is that what you are asking? You cannot say:

但是重新阅读您的问题,这就是您要问的吗?你不能说:

foo <"bar"> x;

but you can say

但你可以说

template <typename T>
struct foo {
   foo( T t ) {}
};

foo <const char *> f( "bar" );

回答by amit

Further from Neil's answer: one way to using strings with templates as you want is to define a traits class and define the string as a trait of the type.

从 Neil 的回答中进一步了解:根据需要使用带有模板的字符串的一种方法是定义一个特征类并将字符串定义为该类型的特征。

#include <iostream>

template <class T>
struct MyTypeTraits
{
   static const char* name;
};

template <class T>
const char* MyTypeTraits<T>::name = "Hello";

template <>
struct MyTypeTraits<int>
{
   static const char* name;
};

const char* MyTypeTraits<int>::name = "Hello int";

template <class T>
class MyTemplateClass
{
    public:
     void print() {
         std::cout << "My name is: " << MyTypeTraits<T>::name << std::endl;
     }
};

int main()
{
     MyTemplateClass<int>().print();
     MyTemplateClass<char>().print();
}

prints

印刷

My name is: Hello int
My name is: Hello

回答by Mooing Duck

You canhave a const char*non-type template parameter, and pass it a const char[]variable with staticlinkage, which is not all that far from passing a string literal directly.

可以有一个const char*非类型模板参数,并通过链接向它传递一个const char[]变量static,这与直接传递字符串文字相去甚远。

#include <iostream>    

template<const char *str> 
struct cts {
    void p() {std::cout << str;}
};

static const char teststr[] = "Hello world!";
int main() {
    cts<teststr> o;
    o.p();
}

http://coliru.stacked-crooked.com/a/64cd254136dd0272

http://coliru.stacked-crooked.com/a/64cd254136dd0272

回答by Monotomy

This is a solution with MPLLIBS to pass a strings as template arguments ( C++11 ).

这是使用 MPLLIBS 将字符串作为模板参数(C++11)传递的解决方案。

#include <iostream>
#include <mpllibs/metaparse/string.hpp> // https://github.com/sabel83/mpllibs
#include <boost/mpl/string.hpp>

// -std=c++11

template<class a_mpl_string>
struct A
{
  static const char* string;
};

template<class a_mpl_string>
const char* A< a_mpl_string >
::string { boost::mpl::c_str< a_mpl_string >::value };  // boost compatible

typedef A< MPLLIBS_STRING ( "any string as template argument" ) > a_string_type;

int main ( int argc, char **argv )
{
  std::cout << a_string_type{}.string << std::endl;
  return 0;
}

prints:

印刷:

any string as template argument

The lib on github: https://github.com/sabel83/mpllibs

github 上的库:https: //github.com/sabel83/mpllibs

回答by AlwaysTraining

inline const wchar_t *GetTheStringYouWant() { return L"The String You Want"; }

template <const wchar_t *GetLiteralFunc(void)>
class MyType
{
     void test()
     {
           std::cout << GetLiteralFunc;
     }    
}

int main()
{
     MyType<GetTheStringYouWant>.test();
}

Try it with pasing the address of a function as the template argument.

尝试将函数的地址作为模板参数传递。

回答by amit

Based on your comments under Niel's answer, another possibility is the following:

根据您在 Niel 回答下的评论,另一种可能性如下:

#include <iostream>

static const char* eventNames[] = { "event_A", "event_B" };

enum EventId {
        event_A = 0,
        event_B
};

template <int EventId>
class Event
{
public:
   Event() {
     name_ = eventNames[EventId];
   }
   void print() {
        std::cout << name_ << std::endl;
   }
private:
   const char* name_;
};

int main()
{
        Event<event_A>().print();
        Event<event_B>().print();
}

prints

印刷

event_A
event_B

回答by Gregory Pakosz

EDIT: ok the title of your question seems to be misleading

编辑:好的,您的问题标题似乎具有误导性

"I want a class which takes two parameters in its constructor. The first can be either an int, double or float, so , and the second is always a string literal "my string", so I guess const char * const."

“我想要一个在其构造函数中带有两个参数的类。第一个可以是 int、double 或 float,所以,第二个始终是字符串文字“我的字符串”,所以我猜是 const char * const。”

It looks like you're trying to achieve:

看起来您正在努力实现:

template<typename T>
class Foo
{
  public:
  Foo(T t,  const char* s) : first(t), second(s)
  {
    // do something
  }

  private:
  T first;
  const char* second;

};

This would work for any type, for the first parameter: int, float, double, whatever.

这适用于任何类型,对于第一个参数:int, float, double, 等等。

Now if you really want to restrict the type of the first parameter to be only int, floator double; you can come up with something more elaborate like

现在,如果您真的想将第一个参数的类型限制为仅int,floatdouble; 你可以想出一些更精细的东西,比如

template<typename T>
struct RestrictType;

template<>
struct RestrictType<int>
{
  typedef int Type;
};

template<>
struct RestrictType<float>
{
  typedef float Type;
};

template<>
struct RestrictType<double>
{
  typedef double Type;
};

template<typename T>
class Foo
{
  typedef typename RestrictType<T>::Type FirstType;

  public:
  Foo(FirstType t,  const char* s) : first(t), second(s)
  {
    // do something
  }

  private:
  FirstType first;
  const char* second;

};

int main()
{
  Foo<int> f1(0, "can");
  Foo<float> f2(1, "i");
  Foo<double> f3(1, "have");
  //Foo<char> f4(0, "a pony?");
}

If you remove the comment on the last line, you'll effectively get a compiler error.

如果您删除最后一行的注释,您实际上会得到一个编译器错误。



String literals are not allowed by C++2003

C++2003 不允许字符串文字

ISO/IEC 14882-2003 §14.1:

ISO/IEC 14882-2003 §14.1:

14.1 Template parameters

A non-type template-parameter shall have one of the following (optionallycv-qualified) types:

— integral or enumeration type,

— pointer to object or pointer to function,

— reference to object or reference to function,

— pointer to member.

14.1 模板参数

非类型模板参数应具有以下(可选的 cv 限定)类型之一:

— 整数或枚举类型,

— 指向对象或指向函数的指针,

— 对对象的引用或对函数的引用,

— 指向成员的指针。

ISO/IEC 14882-2003 §14.3.2:

ISO/IEC 14882-2003 §14.3.2:

14.3.2 Template non-type arguments

A template-argument for a non-type, non-template template-parameter shall be one of:

— an integral constant-expression of integral or enumeration type; or

— the name of a non-type template-parameter; or

— the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or

— a pointer to member expressed as described in 5.3.1.

[Note:A string literal (2.13.4) does not satisfy the requirements of any of these categories and thus is not an acceptable template-argument.

[Example:

14.3.2 模板非类型参数

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

— 整数或枚举类型的整数常量表达式;或者

— 非类型模板参数的名称;或者

— 具有外部链接的对象或函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 & id 表达式,如果名称指的是函数或数组,则 & 是可选的,或者如果相应的模板参数是一个引用;或者

— 指向如 5.3.1 中描述的成员的指针。

[注意:字符串文字 (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 

—end example] —end note]

—结束示例] —结束说明]

And it looks like it's not going to change in the upcoming C++0X, see the current draft 14.4.2 Template non-type arguments.

看起来它不会在即将到来的 C++0X 中改变,请参阅当前草案 14.4.2 Template non-type arguments

回答by ManuelAtWork

You cannot pass a string literal directly as a template parameter.

您不能直接将字符串文字作为模板参数传递。

But you can get close:

但你可以接近:

template<class MyString = typestring_is("Hello!")>
void MyPrint() {
  puts( MyString::data() );
}

...
// or:
MyPrint<typestring_is("another text")>();
...

All you need is a small header file from here.

你所需要的只是一个来自这里的小头文件。



Alternatives:

备择方案:

  • Define a global char const *and pass it to the template as pointer. (here)

    Drawback: Requires additional code outside of the template argument list. It is not suitable, if you need to specify the string literal "inline".

  • Use a non-standard language extension. (here)

    Drawback: Not guaranteed to work with all compilers.

  • Use BOOST_METAPARSE_STRING. (here)

    Drawback: Your code will depend on the Boost library.

  • Use a variadic template parameter pack of char, e.g. str_t<'T','e','s','t'>.

    This is what the above solution does for you behind the scenes.

  • 定义一个全局char const *变量并将其作为指针传递给模板。(这里

    缺点:需要模板参数列表之外的额外代码。如果您需要指定字符串文字“inline”,则不适合。

  • 使用非标准语言扩展。(这里

    缺点:不保证适用于所有编译器。

  • 使用BOOST_METAPARSE_STRING. (这里

    缺点:您的代码将依赖于 Boost 库。

  • 使用 char 的可变参数模板参数包,例如str_t<'T','e','s','t'>.

    这就是上述解决方案在幕后为您所做的。

回答by Prasoon Saurav

I want a class which takes two parameters in its constructor. The first can be either an int, double or float, so , and the second is always a string literal "my string"

我想要一个在其构造函数中带有两个参数的类。第一个可以是 int、double 或 float,所以,第二个始终是字符串文字“我的字符串”

template<typename T>
class demo
{
   T data;
   std::string s;

   public:

   demo(T d,std::string x="my string"):data(d),s(x) //Your constructor
   {
   }
};

I am not sure but is this something what you want?

我不确定,但这是你想要的吗?

回答by Anton Plakhotnyk

Use proxy static constexpr const char type_name_str[] = {"type name"};for passing string as template parameter. Defining string using []is important.

使用代理static constexpr const char type_name_str[] = {"type name"};将字符串作为模板参数传递。定义字符串 using[]很重要。

#include <iostream>

template<typename T, const char* const t_name>
struct TypeName
{
public:

    static constexpr const char* Name()         
    {                                   
        return t_name;
    };                                  

};

static constexpr const char type_name_str[] = {"type name"};

int main() 
{
    std::cout<<TypeName<float, type_name_str>::Name();
    return 0;
}