相关疑难解决方法(0)

是否可以编写模板来检查函数的存在?

是否可以编写一个模板来改变行为,具体取决于是否在类上定义了某个成员函数?

这是我想写的一个简单例子:

template<class T>
std::string optionalToString(T* obj)
{
    if (FUNCTION_EXISTS(T->toString))
        return obj->toString();
    else
        return "toString not defined";
}
Run Code Online (Sandbox Code Playgroud)

所以,如果class T已经toString()确定的话,就使用它; 否则,它没有.我不知道怎么做的神奇部分是"FUNCTION_EXISTS"部分.

c++ templates sfinae template-meta-programming

458
推荐指数
20
解决办法
14万
查看次数

C++中模板参数中auto的优点17

auto在(可能)用C++ 17引入的模板参数中有哪些优点?

它只是auto我想要实例化模板代码的自然扩展吗?

auto v1 = constant<5>;      // v1 == 5, decltype(v1) is int
auto v2 = constant<true>;   // v2 == true, decltype(v2) is bool
auto v3 = constant<'a'>;    // v3 == 'a', decltype(v3) is char
Run Code Online (Sandbox Code Playgroud)

我还从这个语言功能中获得了什么?

c++ templates auto c++17

51
推荐指数
4
解决办法
2万
查看次数

在C++ 11中is_constexpr是否可行?

是否有可能根据C++ 11中的C++ 11表达式是否为常量表达式(即constexpr)生成编译时布尔值?关于SO的几个问题与此有关,但我在任何地方都没有看到直接答案.

c++ compile-time constexpr c++11

32
推荐指数
4
解决办法
3946
查看次数

实现is_constexpr_copiable

我试图实现一个类似于std::is_constructible异常的值模板,只有当类型在constexpr环境中可复制时才是真的(即它的复制构造函数是constexpr限定的).我到达了以下代码:

#include <type_traits>

struct Foo {
    constexpr Foo() = default;
    constexpr Foo(const Foo&) = default;
};
struct Bar {
    constexpr Bar() = default;
    Bar(const Bar&);
};

namespace detail {
template <int> using Sink = std::true_type;
template<typename T> constexpr auto constexpr_copiable(int) -> Sink<(T(T()),0)>;
template<typename T> constexpr auto constexpr_copiable(...) -> std::false_type;
}
template<typename T> struct is_constexpr_copiable : decltype(detail::constexpr_copiable<T>(0)){ };

static_assert( is_constexpr_copiable<Foo>::value, "");
static_assert(!is_constexpr_copiable<Bar>::value, "");
Run Code Online (Sandbox Code Playgroud)

现在我问自己这是否符合标准,因为编译器似乎不同意输出. https://godbolt.org/g/Aaqoah


编辑(c ++ 17功能):

is_constexpr_constructible_from使用c ++ 17的新的自动非类型模板类型实现稍微不同的时候,我再次发现编译器之间的区别,当在constexpr表达式中取消引用nullptr时SFINAE.

#include <type_traits>

struct Foo …
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer constexpr c++17

22
推荐指数
1
解决办法
527
查看次数

在默认模板参数中调用constexpr

在C++ 11中,我使用constexpr函数作为模板参数的默认值 - 它看起来像这样:

template <int value>
struct bar
{
    static constexpr int get()
    {
        return value;
    }
};

template <typename A, int value = A::get()>
struct foo
{
};

int main()
{
    typedef foo<bar<0>> type;

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

G ++ 4.5和4.7编译它,但Clang ++ 3.1没有.来自clang的错误消息是:

clang_test.cpp:10:35: error: non-type template argument is not a constant expression
template <typename A, int value = A::get()>
                                  ^~~~~~~~
clang_test.cpp:17:19: note: while checking a default template argument used here
        typedef foo<bar<3>> type;
                ~~~~~~~~~^~
clang_test.cpp:10:35: note: undefined function …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang constexpr c++11

12
推荐指数
1
解决办法
2017
查看次数

我可以在编译时检测到编译时常量的"函数参数"

我可以在编译时检测"函数参数" 1是否是编译时常量?

例如,一个函数print(int i)可以"constant 5"在被调用时打印,print(5)"non-constant 5"如果被调用为print(i)where,i则是一些非常量变量.特别是,在"is constant"分支中,我应该能够将其i视为constexpr,包括将其用于模板参数等.

宏技巧,模板元编程和SFINAE技巧都可以.理想情况下它是可移植的,但是编译器特定的解决方案总比没有好.

如果存在"错误否定"则可以 - 即,如果常量值有时被检测为非常数(例如,禁用某些优化时).

如果解决方案可以检测到常量值何时间接传递给函数(例如,当一个常量值传递给调用的中间函数print并且随后内联将常量暴露给print)时,可以获得奖励积分.最后一种行为显然取决于优化.

如果它自然延伸到多个参数,则可获得双倍奖励

如果一个人可以使用和不带constexpr参数重载函数的版本,这可能是直截了当的,但你不能.


1我在这里引用"函数参数",因为解决方案并不严格要求在函数内(或在具有特殊参数的调用者/被调用者边界)检测此状态 - 它只需要像函数一样出现给调用者但是可以使用宏或其他技巧,如静态对象operator()等.

c++ optimization constexpr c++11

12
推荐指数
1
解决办法
885
查看次数

功能模板的非依赖默认模板参数是否允许SFINAE?

这里的"非依赖"是指"非依赖于该特定函数模板的任何其他模板参数".

在回答这个问题时,我认为我找到了答案,但根据@Johannes(在我的回答评论中),我在这里误解了标准.采用以下简单示例:

#include <type_traits>

template<class T>
struct X{
  template<class U = typename T::type>
  static void foo(int){}
  static void foo(...){}
};

int main(){
  X<std::enable_if<false>>::foo(0);
}
Run Code Online (Sandbox Code Playgroud)

(现场版.)

以上编译有保证吗?GCC和Clang在这里不同意,可以在实时版本中看到它们之间的切换.有趣的是,GCC接受以下内容:

#include <type_traits>

template<class T>
struct X{
  template<bool = T::f()>
  static void foo(int){}
  static void foo(...){}
};

struct Y{
  static bool f(){ return true; }
};

int main(){
  X<Y>::foo(0);
}
Run Code Online (Sandbox Code Playgroud)

(现场版.)

第二个片段只有foo(int)T包含constexpr静态函数时才会打印f.再说一次,有趣的是,如果你完全f从中删除Y(或通过,int相反),GCC会抱怨缺少一名成员,表明它不允许SFINAE - 这与之前的观察相矛盾.Clang采用所有变化并应用SFINAE,我想知道这是否是标准所保证的. …

c++ templates sfinae language-lawyer

11
推荐指数
1
解决办法
714
查看次数

SFINAE constexpr与std :: get

这是用SFINAE检测constexpr的后续问题.

我想检测一个元组的元素(或任何可以使用的元素std::get)是否为constexpr.所以我编写了以下助手,类似于Xeo给出的:

template<size_t> struct sfinae_true : std::true_type{};

template<size_t N, class T>
auto check(const T& arg) -> sfinae_true<(std::get<N>(arg),N)>;

template<size_t N, class>
std::false_type check(...);
Run Code Online (Sandbox Code Playgroud)

现在我的测试驱动代码:

int main()
{
    constexpr std::tuple<size_t, size_t> arg(4,5);
    typedef decltype(check<0,decltype(arg)>(arg)) is_cexpr;
    std::cout << "is constexpr? " << is_cexpr::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)

但是,这总是打印出来false给我!要检查由于某种原因并不总是调用错误的重载,我注释掉了错误的重载并得到编译器错误:

注意:候选模板被忽略:替换失败[N = 0,T = const std :: tuple]:非类型模板参数不是常量表达式
自动检查(const T&arg) - > sfinae_true <(std :: get( ARG),0)>;

但是,我知道我可以调用std::get<N>(arg)并获得constexpr值:

template<size_t N>
class A{};

int main()
{
    constexpr std::tuple<size_t, size_t> …
Run Code Online (Sandbox Code Playgroud)

c++ sfinae constexpr c++14

8
推荐指数
1
解决办法
584
查看次数

一个概念可以需要 constexpr 值或函数吗?

因此,我想做一些高级的类型级黑客技术,我真的希望能够编写一个概念,要求类型具有constexpr int与其关联的值,稍后我可以在与整数std::array模板参数。

可以写

template<typename T>
concept bool HasCount = requires {
    typename T::count;
};
Run Code Online (Sandbox Code Playgroud)

但这不是我想要的;我想T::count成为一个static constexpr int。但是,代码(甚至不包括所需的constexpr

template<typename T>
concept bool HasCount = requires {
    int T::count;
};
Run Code Online (Sandbox Code Playgroud)

在 GCC 7.3.0 上编译时不会出现“错误:预期的主表达式在 'int' 之前”。

另一个失败的尝试:可以这样写,这需要static int T::count()

template<typename T>
concept bool HasCount = requires {
    {T::count()} -> int;
};
Run Code Online (Sandbox Code Playgroud)

但不是这个,这就是我想要的:

template<typename T>
concept bool HasCount = requires {
    {T::count()} -> constexpr int;
    {T::count() constexpr} -> int; // or …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts

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

在 constexpr 评估上分支/在 constexpr 上重载

设置:

我有一个使用 SIMD 内在函数的函数,并希望在一些 constexpr 函数中使用它。

为此,我需要使其成为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器的常量评估器无法处理它们。

我尝试用执行相同操作的 C++ constexpr 实现替换 SIMD 内在函数。该函数在运行时变慢了 3.5 倍,但我能够在编译时使用它(是吗?)。

问题

如何在常量表达式中使用此函数而不会在运行时减慢程序速度?

一些想法:

  • 为所有编译器添加对编译器常量表达式求值器的常量求值所有 SIMD 内在函数的支持:可能是正确的解决方案,但这是一项不可能完成的任务。

更务实的解决方案是:

  • 重载函数取决于它是否在常量表达式中执行(即提供 constexpr 和非 constexpr 版本)。
  • 或者,在 constexpr 和运行时实现之间的 constexpr 函数内以某种方式分支(即,在分支中检测函数是否在常量表达式内执行)。

无论如何,我愿意接受任何解决我问题的建议。

提示

  • @RMartinhoFernandes 在 Lounge 中建议使用__builtin_constant_p来检测函数参数是否都是常量表达式,在这种情况下,编译器希望至少尝试在编译时评估函数。

失败的尝试

  • @ Jarod42 提出了只使用两个独立函数的直接建议。我想简单地指出为什么这行不通,因为它不是微不足道的。该解决方案假设在调用站点知道函数是否会被 constexpr 评估。但这种情况并非如此。考虑一个调用我的函数的 constexpr 函数,它应该选择哪个版本的函数?它必须选择 constexpr 一个才能编译,但“外部” constexpr 函数仍然可以在运行时评估。在这种情况下,它将使用“慢”编译时实现,因此,这种方法不能解决问题。

c++ simd intrinsics constexpr c++14

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

使用 SFINAE 检查函数是否为 constexpr

我想检查一个函数是否可以在编译期间被评估。我发现了这个,但我不完全理解这个概念。我有几个疑问:

  1. 代码中下面这行的作用是什么?
    template<int Value = Trait::f()>

  2. 每次当我需要检查该函数是否可以在编译时评估时,是否需要将其设为某个结构的成员函数?

PS
我复制链接中的代码,只是为了方便。

template<typename Trait>
struct test
{
    template<int Value = Trait::f()>
    static std::true_type do_call(int){ return std::true_type(); }

    static std::false_type do_call(...){ return std::false_type(); }

    static bool call(){ return do_call(0); }
};

struct trait
{
    static int f(){ return 15; }
};

struct ctrait
{
    static constexpr int f(){ return 20; }
};

int main()
{
   std::cout << "regular: " << test<trait>::call() << std::endl;
   std::cout << "constexpr: " << test<ctrait>::call() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

c++ templates compile-time sfinae constexpr

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