相关疑难解决方法(0)

是否可以在constexpr中使用std :: string?

使用C++ 11,Ubuntu 14.04,GCC默认工具链.

此代码失败:

constexpr std::string constString = "constString";
Run Code Online (Sandbox Code Playgroud)

错误:constexpr变量'constString'的类型'const string {aka const std :: basic_string}'不是文字...因为......'std :: basic_string'有一个非平凡的析构函数

是否有可能使用std::stringconstexpr?(显然不是......)如果是这样,怎么样?是否有另一种方法在一个字符串中使用字符串constexpr

stdstring constexpr c++11

142
推荐指数
5
解决办法
8万
查看次数

C-Style Strings作为模板参数?

C样式字符串可以用作模板参数吗?

我试过了:

template <char *str>
struct X
{
    const char *GetString() const
    {
         return str;
    }
};

int main()
{
    X<"String"> x;
    cout<<x.GetString();
}
Run Code Online (Sandbox Code Playgroud)

虽然我没有对类定义抱怨,但实例化产生'X' : invalid expression as a template argument for 'str'(VC).

c++ string templates

53
推荐指数
5
解决办法
7万
查看次数

使用可变参数模板创建静态数组

stackoverflow上有一个答案(我似乎无法再找到它),它演示了如何在C++ 11中使用可变参数模板在编译时创建静态数组:

template <class T, T... args> 
struct array_
{
    static const T data[sizeof...(args)];
};

template <class T, T... args> 
const T array_<T, args...>::data[sizeof...(args)] = { args... };
Run Code Online (Sandbox Code Playgroud)

可以提供递归元函数以array_使用任意数量的参数进行实例化,然后将这些参数在编译时复制到内部数组中.这是创建元函数以在编译时生成常量数组的有用方法.

但是,一个问题是它依赖于类模板参数来获取填充数组的实际值.这导致一个主要限制:只有积分常数可以用作值模板参数.因此,您无法使用此技术生成自定义类型的数组.

我试着想办法解决这个限制,但不能提出任何建议.有没有办法让这种技术适用于非积分常数?

c++ templates variadic-templates c++11

25
推荐指数
2
解决办法
1万
查看次数

if/else在C++的编译时?

请考虑以下代码:

#include <iostream>
#include <type_traits>

template<typename T> class MyClass
{
    public:
        MyClass() : myVar{0} {;}
        void testIf() {
            if (isconst) {
                myVar;
            } else {
                myVar = 3;
            }
        }
        void testTernary() {
            (isconst) ? (myVar) : (myVar = 3);
        }

    protected:
        static const bool isconst = std::is_const<T>::value;
        T myVar;
};

int main()
{
    MyClass<double> x;
    MyClass<const double> y;
    x.testIf();
    x.testTernary();
    y.testIf(); // <- ERROR
    y.testTernary(); // <- ERROR
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

对于x(非常量),没有问题.但是,即使在编译时知道if/else中的条件,y(const数据类型)也会导致错误.

是否有可能在编译时不编译错误条件?

c++ templates if-statement compilation

14
推荐指数
3
解决办法
2万
查看次数

尝试将字符串文字作为模板参数传递

我正在尝试找到一种将字符串文字作为模板参数传递的舒适方法.我并不关心支持尽可能多的编译器,我正在使用最新版本的g ++ --std=c++0x.

我尝试了很多可能的解决方案,但都让我很失望.我有点放弃,但首先我想知道为什么其中几个失败了.

他们来了:

#include <iostream>
#include <string>

using namespace std;

struct String {
    char const *m_sz;

    constexpr String(char const *a_sz)
        :
    m_sz(a_sz) {}

    char const *operator () () const {
        return m_sz;
    }
};

template<class _rstr>
string const Get() {
    return _rstr();
}

int main() {
    cout << Get<String("hello")>() << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

和:

#include <iostream>
#include <string>

using namespace std;

struct String {
    char const *m_sz;

    constexpr String(char const *a_sz)
        :
    m_sz(a_sz) {} …
Run Code Online (Sandbox Code Playgroud)

c++ string templates literals c++11

7
推荐指数
4
解决办法
1万
查看次数

无法创建字符串文字类型

我想创建一个我可以用作模板参数的字符串文字.它将编译器抛入某种无限循环.有什么问题并修复?

template <char...> struct slit { };

template <typename ...A>
constexpr auto make_slit(char const* const s, A const ...args)
{
  return *s ? make_slit(s + 1, *s, args...) : slit<args...>();
}

int main()
{
  auto const tmp_(make_slit("slit"));

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

强制性错误(带clang++ -std=c++1y):

t.cpp:4:16: fatal error: recursive template instantiation exceeded maximum depth of 256
constexpr auto make_slit(char const* const s, A const ...args)
               ^
t.cpp:6:15: note: in instantiation of function template specialization 'make_slit<char, char, char, char, char, char, char, …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++14

6
推荐指数
1
解决办法
684
查看次数

基于可变参数模板的类成员变量

给定一个类型,名称和默认值的列表,我可以轻松编写一个生成有效c ++代码的工具,该代码声明一个具有每种类型,名称和默认值的成员变量的类.例如,给出列表

  • int,foo,42
  • 漂浮,酒吧,0.1f

(和类名"Baz"),它会生成

class Baz {
    int foo = 42;
    float bar = 0.1f;
}
Run Code Online (Sandbox Code Playgroud)

如果一个工具可以生成这样一个类,编译器不能为我做这个吗?我正在考虑这些方面的事情(注意:这是伪代码):

template <typename ...MemberTypes> class Baz {
    MemberTypes::type... MemberTypes::name... = MemberTypes::default...;
}
Run Code Online (Sandbox Code Playgroud)

上面的类将被创建类似的东西

using MyBaz = Baz<member_type<int, "foo", 42>, member_type<float, "bar", 0.1f>>;
Run Code Online (Sandbox Code Playgroud)

可能出现这种情况的原因:

  • 所有必需的信息都可在编译时获得.外部工具可以轻松完成.
  • 可以以类似的方式创建具有元组而不是专用成员变量的类(从variadic模板参数声明成员变量).
  • 我可以使用模板特化来近似成员的有限组合.
  • 模板元编程是图灵完备的(C++模板Turing-complete?),所以"一切"应该是可能的.

这可能是不可能的原因:

如果可以的话,怎么办呢?如果不可能,为什么不呢?即将到来的c ++ 17在这方面有什么改变吗?

更新:示例问题: 通常,配置数据存储为字符串的层次结构或某种其他形式的"任何类型".但是,这会导致丑陋的代码(config.get<int>("core.timeout"))并阻止编译器帮助解决,例如,typos(config.get<int>("core.timeuot")).

通过使用其真实类型声明每个配置变量,编译器可以检查类型并防止拼写错误.但是,需要使用自定义代码将配置数据读入正确的成员变量.如果添加了新配置开关,则很容易忘记更新此代码.

只需指定所有成员的类型和名称,然后让编译器自动生成类(包括读取配置文件的方法)将会很方便.这是我要求的功能的可能用例.

c++ templates template-meta-programming c++14 c++17

6
推荐指数
1
解决办法
1210
查看次数

为什么将字符串文字传递给调用 std::format 的模板无法编译?

以下代码片段无法在最新版本的 MSVC (Visual Studio 2022 17.2.2) 上编译。相同的代码片段似乎在以前的编译器版本上运行得很好。

#include <iostream>
#include <format>

template <typename First, typename... Args>
inline auto format1(First&& first, Args&&... args) -> decltype(std::format(first, std::forward<Args>(args)...))
{
    return std::format(std::forward<First>(first), std::forward<Args>(args)...);
}
int main()
{
    std::cout << format1("hi {} {}", 123, 456);
}
Run Code Online (Sandbox Code Playgroud)

编译器发出以下错误:

1>ConsoleApplication3.cpp(10,24): message : 失败是由于在其生命周期之外读取变量引起的 1>ConsoleApplication3.cpp(10,24): message : 请参阅“first”的用法 1>ConsoleApplication3.cpp( 14): message : 请参阅正在编译的函数模板实例化 'std::string format<const char(&)[9],int,int>(First,int &&,int &&)' 的引用 1>
with 1> [ 1 > 首先=const char (&)[9] 1> ]

似乎以某种方式将字符串文字转发到 std::format 会使编译器认为它们在其生命周期之外使用。我尝试更改该函数以接受const First& first以及各种其他变体,但错误仍然存​​在。

据我了解,当 …

c++ templates rvalue-reference c++20

5
推荐指数
1
解决办法
745
查看次数

C++20 是否可以让 constexpr 函数返回具有静态 constexpr 数组且值通过宏传递的类型的元组?

经过两三天的尝试,我不得不放弃并编写了一个“最小”测试用例,希望能够证明该问题。

我需要的是一种将字符串文字(作为不带引号的宏参数传递)转换为可在 constexpr 环境中访问的字符串(用前缀连接)的方法(请参阅https://wandbox.org/permlink/Cr6j6fXemsQRycHI真实代码( tm));这意味着,它们(宏参数)应该被字符串化,然后转换为类型(例如 template <... 'h', 'e', 'l', 'l', 'o', ...>)或转换为static constexpr array<char, N>传递的唯一类型的 a (例如 template <... A<1> ...>,其中A<1>::strastatic constexpr array<char, 6>包含内容'h', 'e', 'l', 'l', 'o', '\0'.

我强烈喜欢后者,只有当后者不可能时才选择前者。

为了在简短的测试用例中演示确切的问题/要求,我提出了以下内容:

一些标题...

#include <array>
#include <tuple>
#include <cassert>
#include <string>
#include <iostream>
Run Code Online (Sandbox Code Playgroud)

然后为了演示最终结果应该如何表现:

template<int I>
struct A;

template<>
struct A<0>
{
  static constexpr auto str = std::to_array("abc"); // The string-literal "abc" may NOT appear here.
                                                    // …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20 constexpr-function

5
推荐指数
1
解决办法
573
查看次数