给定一个数组a,我想countof(a)将数组中的元素数作为编译时常量.如果我有一个指针p,我想countof(p)不编译.这似乎应该是(1)直截了当,(2)通常涵盖在SO中,但(1)我无法使它工作,并且(2)搜索SO没有发现任何东西.
这是我的尝试.
#include <cstddef>
#include <type_traits>
template<typename T, std::size_t n,
typename = typename std::enable_if<std::is_array<T>::value>::type>
constexpr std::size_t countof(T (&)[n]) { return n; }
template<typename T,
typename = typename std::enable_if<std::is_pointer<T>::value>::type>
void countof(T*) = delete;
int main()
{
int a[10];
auto asize = countof(a); // should compile
static_assert(countof(a) == 10,
"countof(a) != 10!");
int *p;
auto psize = countof(p); // shouldn't compile
}
Run Code Online (Sandbox Code Playgroud)
救命?
我正在尝试operator T()使用SFINAE 重载以在T基本类型时返回副本,并在T类时使用const引用.
在double下面的示例中使用a 时,我无法std::is_class删除第二个重载(with ).
也就是说,我得到的错误是:
error: no type named ‘type’ in ‘struct std::enable_if<false, const double&>’
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
^
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
#include <iostream>
#include <type_traits>
template<typename T>
struct Foo
{
operator typename std::enable_if<!std::is_class<T>::value, T >::type () const
{
return _val;
}
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
{
return _val;
}
T _val;
};
int main()
{
Foo<double> f1;
f1._val = 0.3; …Run Code Online (Sandbox Code Playgroud) 鉴于此模板:
template <class A>
struct Something {
... // members common to all template instantiations for all A types
SpecialType member; // but not this - I want this to be conditional...
}
Run Code Online (Sandbox Code Playgroud)
...我想使用"enable_if"使SpecialType成员有条件存在; 也就是说,只有在使用A = SpecialCase1或SpecialCase2类型实例化模板时.在所有其他情况下,我希望SpecialType成员丢失.
如果你想知道为什么,这是关于优化 - 即不在结构中携带无用的有效载荷.我是模板元编程的新手,但我知道我需要"enable_if"和两个"is_same" - 不确定究竟如何,但......
编辑:使用通用C++(即没有特定于Boost)是一个优点.
我正在编写一个简单的向量类,我希望有一些成员函数只能在某些长度的向量中使用(例如,3元素向量的交叉乘积).我偶然发现了std :: enable_if,看起来它可能能够做我想要的,但我似乎无法让它正常工作.
#include <iostream>
#include <type_traits>
template<typename T, unsigned int L>
class Vector
{
private:
T data[L];
public:
Vector<T,L>(void)
{
for(unsigned int i = 0; i < L; i++)
{
data[i] = 0;
}
}
T operator()(const unsigned int i) const
{
return data[i];
}
T& operator()(const unsigned int i)
{
return data[i];
}
Vector<typename std::enable_if<L==3, T>::type, L> cross(const Vector<T,L>& vec2) const
{
Vector<T,L> result;
result(0) = (*this)(1) * vec2(2) - (*this)(2) * vec2(1);
result(1) = (*this)(2) * vec2(0) …Run Code Online (Sandbox Code Playgroud) 我正在创建一个非常小的C++项目,我想根据自己的需要创建一个简单的矢量类.该std::vector模板类不会做.当向量类由chars(即vector<char>)组成时,我希望它能够与a进行比较std::string.经过一番乱搞之后,我编写的代码既可以编译也可以执行我想要的操作.见下文:
#include <string>
#include <stdlib.h>
#include <string.h>
template <typename ElementType>
class WorkingSimpleVector {
public:
const ElementType * elements_;
size_t count_;
// ...
template <typename ET = ElementType>
inline typename std::enable_if<std::is_same<ET, char>::value && std::is_same<ElementType, char>::value, bool>::type
operator==(const std::string & other) const {
if (count_ == other.length())
{
return memcmp(elements_, other.c_str(), other.length()) == 0;
}
return false;
}
};
template <typename ElementType>
class NotWorkingSimpleVector {
public:
const ElementType * elements_;
size_t count_;
// ... …Run Code Online (Sandbox Code Playgroud) 以下代码无法编译,我只是无法弄清楚原因.
template <class T, class... Ts>
typename std::enable_if<sizeof...(Ts) > 0>::type func() {
// nop
}
Run Code Online (Sandbox Code Playgroud)
产生的错误消息是:
error: expected unqualified-id before numeric constant
typename std::enable_if<sizeof...(Ts) > 0u>::type func() {
^
Run Code Online (Sandbox Code Playgroud) c++ enable-if template-meta-programming variadic-templates c++11
例如,如果我有
#include <type_traits>
struct OwnershipReceiver
{
template <typename T,
class = typename std::enable_if
<
!std::is_lvalue_reference<T>::value
>::type
>
void receive_ownership(T&& t)
{
// taking file descriptor of t, and clear t
}
};
Run Code Online (Sandbox Code Playgroud)
海报使用!std::is_lvalue_reference而不是立即更明显std::is_rvalue_reference.我已经在我自己的代码中验证了这一点,前者有效,后者没有.
任何人都可以解释为什么明显不起作用?
最小的例子相当短:
\n#include <iostream>\n#include <array>\n#include <type_traits>\n\nstruct Foo{\n //template <class C>\n //Foo(C col, typename std::enable_if<true,C>::type* = 0){\n // std::cout << "optional argument constructor works" << std::endl;\n //}\n template <class C>\n Foo(typename std::enable_if<true, C>::type col){\n std::cout << "no optional argument constructor works NOT" << std::endl;\n }\n};\n\nint main()\n{\n auto foo = Foo(std::array<bool,3>{0,0,1});\n}\nRun Code Online (Sandbox Code Playgroud)\n第一个构造函数按预期工作。但是第二个构造函数无法编译,我得到
\n\n\n错误:没有匹配的函数可调用 \xe2\x80\x98Foo::Foo(std::array)\xe2\x80\x99
\n
然而给出的解释
\n\n\n注意:模板参数推导/替换失败
\n
没有帮助,正如std::enable_if<true, C>::type应该的C那样,两个构造函数中的第一个参数对于编译器来说应该看起来完全相同。我显然错过了一些东西。为什么编译器的行为不同?对于不使用可选参数的构造函数和enable_if,是否有其他解决方案?
完整的错误消息:
\nmain.cpp:18:45: error: no matching function for call to …Run Code Online (Sandbox Code Playgroud) 我试图实现一个将泛型类型转换为字符串的函数.积分类型需要使用std::to_string(),字符串和字符使用std::string()和矢量,逐个元素,使用其他方法之一(取决于其内容)转换为字符串.
这就是我所拥有的:
//Arithmetic types
template<class T>
typename std::enable_if<std::is_arithmetic<T>::value, std::string>::type convertToString(const T& t){
return std::to_string(t);
}
//Other types using string ctor
template<class T>
typename std::enable_if<std::__and_<std::__not_<std::is_arithmetic<T>>::type,
std::__not_<std::is_same<T, <T,
std::vector<typename T::value_type, typename T::allocator_type>>::value
>>>::value, std::string>::type convertToString(const T& t){
return std::string(t);
}
//Vectors
template<class T>
typename std::enable_if<std::is_same<T, std::vector<typename T::value_type,
typename T::allocator_type>>::value, std::string>::type convertToString(const T& t){
std::string str;
for(std::size_t i = 0; i < t.size(); i++){
str += convertToString(t[i]);
}
return str;
}
Run Code Online (Sandbox Code Playgroud)
问题是第二个函数没有编译.如何设计第二个函数以便它编译(和工作)并且不会产生歧义问题?
我对部分模板特化有点困惑...我有一些代码依赖于算术数据类型T,并且在一个小的整数DIM上.我希望能够为不同的DIM值指定不同的类方法.使用部分模板专业化的不可能性使我探索了enable_if.这正是我所需要的...除了我希望它返回一个数字而不是一个类型.我怎样才能做到这一点?以下代码应说明我想要的内容.
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo{
public:
T function();
};
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 1>::value>::function(){
// do something
return 1.0;
}
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 2>::value>::function(){
// do something else
return 2342.0;
}
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)