Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将常量char*作为模板参数传递_C++_String_Templates - Fatal编程技术网

C++ 将常量char*作为模板参数传递

C++ 将常量char*作为模板参数传递,c++,string,templates,C++,String,Templates,为什么不能在这里传递文本字符串?我做了一个很小的变通 template<const char* ptr> struct lols { lols() : i(ptr) {} std::string i; }; class file { public: static const char arg[]; }; decltype(file::arg) file::arg = __FILE__; // Getting the right type declaration

为什么不能在这里传递文本字符串?我做了一个很小的变通

template<const char* ptr> struct lols {
    lols() : i(ptr) {}
    std::string i;
};
class file {
public:
    static const char arg[];
};
decltype(file::arg) file::arg = __FILE__;
// Getting the right type declaration for this was irritating, so I C++0xed it.

int main() {
    // lols<__FILE__> hi; 
    // Error: A template argument may not reference a non-external entity
    lols<file::arg> hi; // Perfectly legal
    std::cout << hi.i;
    std::cin.ignore();
    std::cin.get();
}
模板结构lols{
lols():i(ptr){}
std::字符串i;
};
类文件{
公众:
静态常量字符参数[];
};
decltype(文件::arg)文件::arg=__文件_;;
//为此获取正确的类型声明是令人恼火的,因此我使用了C++0xE。
int main(){
//哈哈哈;
//错误:模板参数不能引用非外部实体
lols hi;//完全合法

std::cout因为这不是一个有用的实用程序。因为它们不是模板参数的允许形式,所以它目前不起作用

让我们假设它们可以工作。因为对于使用的相同值,它们不需要具有相同的地址,所以即使代码中有相同的字符串文本值,也会得到不同的实例化

lols<"A"> n;

// might fail because a different object address is passed as argument!
lols<"A"> n1 = n;
lolsn;
//可能会失败,因为另一个对象地址作为参数传递!
lols n1=n;

您可以为文本编辑器编写一个插件,用逗号分隔的字符文本列表替换字符串,然后返回。使用可变模板,您可以“解决”在某种程度上,这个问题是这样的。

这是可能的,但模板参数必须具有外部链接,这就排除了使用文本字符串,并降低了执行此操作的实用性

我举的一个例子是:

template<const char* name, const char* def_value=empty_>
struct env : public std::string
{
    env()
    {
        const char* p = std::getenv(name);
        assign(p ? p : def_value);
    }
};

extern const char empty_[] = "";

std::string test = env<empty_>();
模板
结构环境:公共标准::字符串
{
环境()
{
const char*p=std::getenv(名称);
分配(p?p:def_值);
}
};
extern const char empty_[]=“”;
std::string test=env();

我就是这样做的。这对我来说更有意义:

struct MyString { static const std::string val; }
const std::string MyString::val = "this is your string";

template<typename T>
void func()
{
  std::cout << T::val << std::endl;
}

void main()
{
  func<MyString>();
}
struct MyString{static const std::string val;}
const std::string MyString::val=“这是您的字符串”;
模板
void func()
{

std::cout这适用于类,而且,依我看,这很有用。实现速度快且不干净,但很容易变得更干净:

#include <stdio.h>
#include <string.h>

struct TextTag { const char *text; };

template <const TextTag &TRUE, const TextTag &FALSE>
struct TextTaggedBool
{
  const char *GetAsText() const { return m_value ? TRUE.text: FALSE.text; }
  void SetByText(const char *s) { m_value = !strcmp(s, TRUE.text); }
  bool m_value;
};

class Foo
{
public:
    void method()
    {
        m_tbool.SetByText("True!");  printf("%s\n", m_tbool.GetAsText());
        m_tbool.SetByText("False!"); printf("%s\n", m_tbool.GetAsText());
        m_tbool.m_value = true;  printf("%s\n", m_tbool.GetAsText());
        m_tbool.m_value = false; printf("%s\n", m_tbool.GetAsText());
    }

private:
    static constexpr TextTag TrueTag = { "True!" };
    static constexpr TextTag FalseTag = { "False!" };
    TextTaggedBool<TrueTag, FalseTag> m_tbool;
};

void main() { Foo().method(); }
#包括
#包括
结构TextTag{const char*text;};
模板
结构TextTaggedBool
{
const char*GetAsText()const{返回m_值?TRUE.text:FALSE.text;}
void SetByText(const char*s){m_value=!strcmp(s,TRUE.text);}
布尔m_值;
};
福班
{
公众:
void方法()
{
m_tbool.SetByText(“True!”);printf(“%s\n”,m_tbool.GetAsText());
m_tbool.SetByText(“False!”);printf(“%s\n”,m_tbool.GetAsText());
m_tbool.m_value=true;printf(“%s\n”,m_tbool.GetAsText());
m_tbool.m_value=false;printf(“%s\n”,m_tbool.GetAsText());
}
私人:
静态constexpr TextTag TrueTag={“True!”};
静态constexpr TextTag False tag={“False!”};
TextTaggedBool m_tbool;
};
void main(){Foo().method();}
输出:

真的! 假的! 真的!
False!

问得好,我想我会把我的帽子扔进戒指里……我想你可以把指向静态变量的指针作为非类型模板参数传递。从C++20来看,这似乎不会是一个问题……在那之前,这里有一些便宜的宏让它工作

template <const char *Name, typename T>
struct TaggedValue {
  static constexpr char const *name{Name};
  T value;
  friend ostream &operator<<(ostream &o, const TaggedValue &a) {
    return o << a.name << " = " << a.value;
  }
};

#define ST(name, type)\
  const char ST_name_##name[]{#name};\
  using name = TaggedValue<ST_name_##name,type>;

ST(Foo, int);
ST(Bar, int);
ST(Bax, string);

int main() {
  cout << Foo{3} << endl;
  cout << Bar{5} << endl;
  cout << Bax{"somthing"} << endl;
}
模板
结构标记值{
静态constexpr char const*name{name};
T值;

friend ostream&operator
const char file::arg[]=\uuuuu file\uuuuu;
这应该允许您返回到C++03:)。@Kenny:我试过了。编译器抛出错误。@Dead:Odd.g++编译很好(带-pedantic)@Kenny:令人恼火的是,我一直认为这是不可能的。现在我有了它,我似乎无法让它做任何有趣或有用的事情。请注意,如果在命名空间范围内,您将需要
extern const char arg[]=\uu FILE\uuu;
来提供数组外部链接(默认情况下,const对象具有内部链接)。只是回避了一个问题,为什么他们不给他们相同的地址。@DeadMG因为字符串文字“A”在某些上下文中可能是立即数,但根本没有地址?@SlashV我知道已经有一段时间了,但您是否愿意对此进行扩展?我对解释也有点感兴趣。@Zadirion..还有一段时间。鉴于模板参数需要获取其地址,编译器需要为字符串提供唯一的地址文字“A”。这对编译器来说是一个不必要的限制。文字“A”可能是内存中某个地方的常量(并且有一个地址),但编译器可能有多个副本,因此地址不是唯一的,或者文字“A”可能是机器代码指令的“立即”操作数,因此不在任何位置的数据内存中,因此根本没有地址。@SlashV:这是完全错误的。该语言已经要求编译器在许多上下文中合并全局变量(例如内联函数)。强制他们将字符串文本集合在一起并没有多少困难。至于immediates,字符串文本必须具有程序持续时间存储,因此将字符串文本的内容存储在immediate中已经是非法的……除了您不应该从
namespace std