假设以下情况:
类型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
为什么我的代码有奇怪的输出?如何以正确的方式测试类型?
#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"为什么我有两个不同的输出?它们不是同一类型吗?
我很喜欢增加可变参数模板,并开始摆弄这个新功能.我试图了解std::index_sequences 的实现细节(用于元组实现).我看到那里的示例代码,但我真的想要逐步解释如何std::index_sequence编码和每个阶段的元编程主题.想真的傻了:)
c++ templates template-meta-programming variadic-templates c++14
我正在编写一个非常简单的模板类,使用元编程在编译时计算总和,如下所示:
#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 <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:
sum.cpp:9:14:错误:模板实例化深度超过1024的最大值(使用-ftemplate-depth …
我正在尝试使用来自Eigen 3的Matrix类作为我的状态向量来利用Boost的ODE集成功能,但我遇到了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) 在使用编译时字符串(可变参数列表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
考虑以下程序:
#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助手有重新排序的元组类型,使得两个元与萨姆斯的类型,但有序的不同导致相同的元组类型:它可以是第一个,第二个,甚至是另一个问题:它只是有相同的大小,相同的元素,但以一个独特的顺序(无论这个顺序如何).
是否可以使用模板元编程技术在编译时执行此操作?
我需要知道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)
我怎样才能获得这些信息?
在某些情况下,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
对于实现条件类型,我非常喜欢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_t用std::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