标签: template-meta-programming

带有两个不同类型参数的隐式模板类型推导

假设以下情况:

类型A和类型B,B可以隐式转换为A但反之则是不真实的.

我有一个功能

template<class T>
void do_stuff(T a, T b);
Run Code Online (Sandbox Code Playgroud)

我想这样调用所述函数:

do_stuff(A{}, B{});
Run Code Online (Sandbox Code Playgroud)

这里的问题是编译器无法推断出类型,而是说:

template argument deduction/substitution failed
Run Code Online (Sandbox Code Playgroud)

我可以这样调用我的函数:

do_stuff<A>(A{}, B{});
Run Code Online (Sandbox Code Playgroud)

但这对用户来说更烦人.

或者我可以做这样的事情:

template<class T, class M>
void do_stuff(T a, M b);
Run Code Online (Sandbox Code Playgroud)

但是b继续以它的快乐方式成为B类(具有先前的调用).

理想情况下,我想要像:

template<class T, class M = T>
void do_stuff(T a, M b);
Run Code Online (Sandbox Code Playgroud)

要么:

template<class T@INSERT MAGIC SO THAT T IS DEDUCED AS BEING THE TYPE OF ARGUMENT NR 1@>
void do_stuff(T a, T b);
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

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

15
推荐指数
3
解决办法
1123
查看次数

如何检测类型是否为std :: tuple?

为什么我的代码有奇怪的输出?如何以正确的方式测试类型?

#include <iostream>
#include <tuple>
#include <type_traits>

template<typename T> struct is_tuple : std::false_type {};
template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {};

struct TraitBlock {
    using BlockLocation = struct { std::uint64_t x, y, z; };
};

struct TraitRock {};

struct ItemTemplate{
    static constexpr auto traits = std::make_tuple(
        TraitBlock{},
        TraitRock{}
    );
};

int main(){
    using A = std::tuple<char, int,double,char>;
    std::cout << is_tuple<decltype(ItemTemplate::traits)>::value 
    << is_tuple<decltype(std::make_tuple(
        TraitBlock{},
        TraitRock{}
    ))>::value
    << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我用mingw64-GCC 7.2.0与-std = C++ 17,我得到了输出"01"为什么我有两个不同的输出?它们不是同一类型吗?

c++ sfinae template-meta-programming c++11

15
推荐指数
3
解决办法
1339
查看次数

std :: make_index_sequence和std :: index_sequence的详细信息

我很喜欢增加可变参数模板,并开始摆弄这个新功能.我试图了解std::index_sequences 的实现细节(用于元组实现).我看到那里的示例代码,但我真的想要逐步解释如何std::index_sequence编码和每个阶段的元编程主题.想真的傻了:)

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

15
推荐指数
2
解决办法
8214
查看次数

模板元编程递归上限?

我正在编写一个非常简单的模板类,使用元编程在编译时计算总和,如下所示:

#include <iostream>

using namespace std;

template<int N>
class Sum
{
    public:
        enum {value = N + Sum<N-1>::value };
};

template<>
class Sum<0>
{
    public:
        enum {value = 0};
};


int main()
{
    cout << Sum<501>::value << endl;
}
Run Code Online (Sandbox Code Playgroud)

有趣的是:

  • 当我打印Sum <500>及以下时,它工作正常
  • 当谈到Sum <501>时,编译失败了:

    sum.cpp:9:从Sum<500>' sum.cpp:9: instantiated fromSum <501>'sum.cpp:22实例化:从这里实例化

    sum.cpp:9:错误:不完整的类型Sum<1>' used in nested name specifier sum.cpp:9: error: enumerator value for值'不是整数常量

  • Sum <501>将报告Sum <1>的错误,Sum <502>将报告Sum <2>的错误,差值始终为2,在我看来编译器的限制资源为500.

对此有何想法?他们是打破这种限制的一种方式吗?

谢谢.

编辑:
谢谢大家,重点不是关于算法,而是编译器的限制 - 我知道有一个简单的方法来获得总和:)

EDIT2:

  • 使用gcc 4.6 +,错误信息更有帮助

    sum.cpp:9:14:错误:模板实例化深度超过1024的最大值(使用-ftemplate-depth …

c++ templates template-meta-programming

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

使用带有Eigen :: Matrix的Boost :: odeint作为状态向量

我正在尝试使用来自Eigen 3Matrix类作为我的状态向量来利用BoostODE集成功能,但我遇到了Boost深入的问题,我不明白如何解决.

我正在尝试做的最小例子:

#include <Eigen/Core>
#include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp>
#include <iostream>

using namespace Eigen;
using namespace boost::numeric::odeint;

template<size_t N>
using vector = Matrix<double, N, 1>;

typedef vector<3> state;

int main() {

    state X0;
    X0 << 1., 2., 3.;
    state xout = X0;

    runge_kutta_dopri5<state> stepper;

    // If I remove these lines, everything compiles fine
    stepper.do_step([](const state x, state dxdt, const double t) -> void { 
        dxdt = x;
    }, X0, 0.0, xout, 0.01);

    std::cout << …
Run Code Online (Sandbox Code Playgroud)

c++ templates boost eigen template-meta-programming

14
推荐指数
1
解决办法
2346
查看次数

懒惰评估(短路)模板条件类型的通用方法

在使用编译时字符串(可变参数列表char)操作时,我需要实现一种检查编译时字符串是否包含另一个(较小的)编译时字符串的方法.

这是我的第一次尝试:

template<int I1, int I2, typename, typename> struct Contains;

template<int I1, int I2, char... Cs1, char... Cs2> 
struct Contains<I1, I2, CharList<Cs1...>, CharList<Cs2...>>
{
    using L1 = CharList<Cs1...>;
    using L2 = CharList<Cs2...>;
    static constexpr int sz1{L1::size};
    static constexpr int sz2{L2::size};

    using Type = std::conditional
    <
        (I1 >= sz1),
        std::false_type,
        std::conditional
        <
            (L1::template at<I1>() != L2::template at<I2>()),
            typename Contains<I1 + 1, 0, L1, L2>::Type,
            std::conditional
            <
                (I2 == sz2 - 1),
                std::true_type,
                typename Contains<I1 + 1, I2 + 1, …
Run Code Online (Sandbox Code Playgroud)

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

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

如何在编译时订购类型?

考虑以下程序:

#include <tuple>
#include <vector>
#include <iostream>
#include <type_traits>

template <class T>
struct ordered {};

template <class... T>
struct ordered<std::tuple<T...>>
{
    using type = /* a reordered tuple */;
};

template <class T>
using ordered_t = typename ordered<T>::type;

int main(int argc, char* argv[])
{
    using type1 = std::tuple<char, std::vector<int>, double>;
    using type2 = std::tuple<std::vector<int>, double, char>;
    std::cout << std::is_same_v<type1, type2> << "\n"; // 0
    std::cout << std::is_same_v<ordered_t<type1>, ordered_t<type2>> << "\n"; // 1
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

ordered助手有重新排序的元组类型,使得两个元与萨姆斯的类型,但有序的不同导致相同的元组类型:它可以是第一个,第二个,甚至是另一个问题:它只是有相同的大小,相同的元素,但以一个独特的顺序(无论这个顺序如何).

是否可以使用模板元编程技术在编译时执行此操作?

c++ types tuples template-meta-programming c++17

14
推荐指数
1
解决办法
519
查看次数

计算lambda中的参数数量

我需要知道lambda具有的确切参数数量.我不关心他们的类型,我只需要一个计数.

auto lambda0 = [&]() { ... };
auto lambda1 = [&](int32_t a) { ... };
auto lambda2 = [&](int32_t a, auto b) { ... };

lambda_details<decltype(lambda0)>::argument_count; // Equals 0
lambda_details<decltype(lambda1)>::argument_count; // Equals 1
lambda_details<decltype(lambda2)>::argument_count; // Equals 2
Run Code Online (Sandbox Code Playgroud)

检测变量lambda也很好,所以我也可以处理那个边缘情况.

auto lambda_variadic = [&](auto... args){ ... };

lambda_details<decltype(lambda_variadic)>::is_variadic; // Equals true
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得这些信息?

c++ lambda template-meta-programming generic-lambda c++14

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

C ++通用编译时循环

在某些情况下,for在编译时评估/展开循环可能是有用/必要的。例如,要遍历a的元素tuple,需要使用std::get<I>,这取决于模板int参数I,因此必须在编译时对其进行评估。使用编译递归可以解决一个特定的问题,例如此处此处以及std::tuple 此处专门讨论的问题。

但是,我对如何实现通用编译时for循环感兴趣。

以下c++17代码实现了这个想法

#include <utility>
#include <tuple>
#include <string>
#include <iostream>

template <int start, int end, template <int> class OperatorType, typename... Args>
void compile_time_for(Args... args)
{
  if constexpr (start < end)
         {
           OperatorType<start>()(std::forward<Args>(args)...);
           compile_time_for<start + 1, end, OperatorType>(std::forward<Args>(args)...);
         }    
}

template <int I>
struct print_tuple_i {
  template <typename... U>
  void operator()(const std::tuple<U...>& x) { std::cout << std::get<I>(x) …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming variadic-templates c++17 c++20

14
推荐指数
1
解决办法
1235
查看次数

有没有一种很好的方法来使用默认失败情况实现条件类型?

对于实现条件类型,我非常喜欢std::conditional_t它,因为它使代码简短且可读性强:

template<std::size_t N>
using bit_type =
    std::conditional_t<N == std::size_t{  8 }, std::uint8_t,
    std::conditional_t<N == std::size_t{ 16 }, std::uint16_t,
    std::conditional_t<N == std::size_t{ 32 }, std::uint32_t, 
    std::conditional_t<N == std::size_t{ 64 }, std::uint64_t, void>>>>;
Run Code Online (Sandbox Code Playgroud)

使用它非常直观:

bit_type<8u> a;  // == std::uint8_t
bit_type<16u> b; // == std::uint16_t
bit_type<32u> c; // == std::uint32_t
bit_type<64u> d; // == std::uint64_t
Run Code Online (Sandbox Code Playgroud)

但是,由于这是纯条件类型void,因此在这种情况下必须有默认类型- 。因此,如果N还有其他值,则该类型将产生:

bit_type<500u> f; // == void
Run Code Online (Sandbox Code Playgroud)

现在,它不会编译,但是yielding类型仍然有效。

意味着您可以说bit_type<500u>* f;并且将拥有一个有效的程序!

那么,当达到条件类型的失败情况时,有没有一种好的方法让编译失败?


一个想法立即将取代过去std::conditional_tstd::enable_if_t

template<std::size_t N>
using bit_type …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-meta-programming c++11 conditional-types

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