在C ++ 17中,此代码是非法的:
constexpr int foo(int i) {
return std::integral_constant<int, i>::value;
}
Run Code Online (Sandbox Code Playgroud)
这是因为即使foo
可以在编译时进行评估,编译器仍然需要产生指令以在运行时执行它,从而使模板实例化成为不可能。
在C ++ 20中,我们将具有consteval
需要在编译时评估的函数,因此应删除运行时约束。这是否意味着该代码将是合法的?
consteval int foo(int i) {
return std::integral_constant<int, i>::value;
}
Run Code Online (Sandbox Code Playgroud) 根据https://en.cppreference.com/,std::vector<bool>
具有类模板专业化,而std::array<bool, N>
没有。不提供的原因有哪些?
c++ stdvector template-specialization class-template stdarray
以下程序
#include <algorithm>
#include <utility>
#include <memory>
namespace my_namespace
{
template<class T>
void swap(T& a, T& b)
{
T tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
template<class T, class Alloc = std::allocator<T>>
class foo {};
}
int main()
{
my_namespace::foo<int> *a, *b;
using my_namespace::swap;
swap(a,b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
导致两者g++
并clang
在我的系统上发出以下编译器错误:
$ clang -std=c++11 swap_repro.cpp -I.
swap_repro.cpp:28:3: error: call to 'swap' is ambiguous
swap(a,b);
^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/algorithmfwd.h:571:5: note: candidate function [with _Tp = my_namespace::foo<int, std::allocator<int> > …
Run Code Online (Sandbox Code Playgroud) c++ namespaces class-template name-lookup argument-dependent-lookup
我想有一个模板类(如float
/double
类型),但我使用Nvidia的CUDA和Optix公司和有多个其他类型(例如float2
,double2
,float3
,...)依赖于所选择的模板类型。
像这样的东西:
#include <optixu/optixu_vector_types.h>
#include <type_traits>
template <class T>
class MyClass
{
MyClass()
{
if (std::is_same<T, float>::value)
{
typedef optix::float2 T2;
}
else if (std::is_same<T, double>::value)
{
typedef optix::double2 T2;
}
T2 my_T2_variable;
}
void SomeFunction()
{
T2 another_T2_variable;
};
};
Run Code Online (Sandbox Code Playgroud)
我现在的解决方案是有多个模板参数MyClass<T,T2,T3> my_object;
,但这似乎有太多的开销和混乱。有没有办法使用上述所需的单个模板参数实现相同的目标?
在这个Q&A中,我编写了一个小包装类,它提供了对范围的反向迭代器访问,依赖于类模板的c ++ 1z语言特征模板参数推导(p0091r3,p0512r0)
#include <iostream>
#include <iterator>
#include <vector>
template<class Rng>
class Reverse
{
Rng const& rng;
public:
Reverse(Rng const& r) noexcept
:
rng(r)
{}
auto begin() const noexcept { using std::end; return std::make_reverse_iterator(end(rng)); }
auto end() const noexcept { using std::begin; return std::make_reverse_iterator(begin(rng)); }
};
int main()
{
std::vector<int> my_stack;
my_stack.push_back(1);
my_stack.push_back(2);
my_stack.puhs_back(3);
// prints 3,2,1
for (auto const& elem : Reverse(my_stack)) {
std::cout << elem << ',';
}
}
Run Code Online (Sandbox Code Playgroud)
但是,执行嵌套应用程序Reverse
不会产生原始迭代顺序 …
在我发现MSVC和GCC(也可能是clang)之间在编译和链接相同代码时的不兼容之后,我很好奇这个程序是否实际编译和链接,因此它是MSVC中的错误(报告链接器错误)或应该我用不同的方式写它.该计划包括3个文件:
章
template <typename T>
struct A
{
void func() {};
};
template <>
void A<int>::func ();
Run Code Online (Sandbox Code Playgroud)
A.cpp:
#include "C.h"
int main()
{
A<int> x;
x.func();
}
Run Code Online (Sandbox Code Playgroud)
B.cpp:
#include "C.h"
template <>
void A<int>::func()
{
}
Run Code Online (Sandbox Code Playgroud)
MSVC产生的链接器错误是:
A.obj:错误LNK2019:未解析的外部符号"public:void __thiscall A :: func(void)"
所以基本上它决定不在定义中创建符号B.cpp
.让我强烈怀疑它是一个错误的东西是移动func
结构定义的非特定定义,甚至将它放在特化声明之上使程序成功,但我想确定.
所以我的问题是 - 是否应该通过符合标准的编译器/链接器编译和链接此程序而不会出错?
我有以下代码:
template <class T>
class lit {
public:
lit(T l) : val(l) {}
T val;
};
template <class T>
class cat {
public:
cat(lit<T> const& a, lit<T> const& b) : a(a), b(b) {}
lit<T> const& a;
lit<T> const& b;
};
template <class T>
cat<T> operator+(lit<T> const& a, lit<T> const& b) {
return cat(a, b);
}
int main() {
auto r1 = cat((lit ('b')), lit('d')); // compiles
auto r2 = (lit ('b')) + lit('d') ; // doesn't compile
auto r3 = …
Run Code Online (Sandbox Code Playgroud) c++ templates class-template template-argument-deduction c++17
我试图使用奇怪的重复模板模式实现静态多态性,当我注意到static_cast<>
,通常在编译时检查一个类型是否实际可以转换为另一个,在基类声明中错过了一个错误,允许代码向下转换基础与其中一个兄弟姐妹同课:
#include <iostream>
using namespace std;
template< typename T >
struct CRTP
{
void do_it( )
{
static_cast< T& >( *this ).execute( );
}
};
struct A : CRTP< A >
{
void execute( )
{
cout << "A" << endl;
}
};
struct B : CRTP< B >
{
void execute( )
{
cout << "B" << endl;
}
};
struct C : CRTP< A > // it should be CRTP< C >, but typo …
Run Code Online (Sandbox Code Playgroud) 如果我有一个默认模板类型的模板类,但我必须写模板尖括号.有可能避免这种情况吗?
例:
template <typename T=int>
class tt {
public:
T get() { return 5; }
};
...
tt<> t; // how to avoid <>
std::cout << t.get() << std::endl;
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已通过单独的命名空间完成此操作并重新声明该类:
namespace detail_ {
template <typename T=int>
class tt {
public:
T get() { return 5; }
};
}
class tt : public detail_::tt {}
...
tt t;
std::cout << t.get() << std::endl;
Run Code Online (Sandbox Code Playgroud)
问题是,如果我想使用其他类型的类,我必须去名称空间detail_.有没有其他解决方案,我还没有看到.
指定的初始化程序(C ++ 20)应该如何与CTAD一起使用?
这段代码在gcc9.2中可以正常工作,但在clang8中失败
template <typename int_t=int, typename float_t=float>
struct my_pair {
int_t first;
float_t second;
};
template<typename ... ts>
my_pair(ts...) -> my_pair<ts...>;
int main() {
my_pair x{.first = 20, .second = 20.f};
static_assert( std::is_same_v<decltype(x.first), int> );
static_assert( std::is_same_v<decltype(x.second), float> );
}
Run Code Online (Sandbox Code Playgroud)
这应该是有效的吗?
c++ designated-initializer class-template argument-deduction c++20
c++ ×10
class-template ×10
templates ×4
c++17 ×2
c++20 ×2
c++11 ×1
class ×1
coding-style ×1
constexpr ×1
name-lookup ×1
namespaces ×1
static-cast ×1
stdarray ×1
stdvector ×1
template-argument-deduction ×1
visual-c++ ×1