C++::STD::EnableαIF和Virtual:
我已经扫描了答案,但是。。。这些问题似乎很愚蠢 我非常高兴,也完全理解我怎么强调都不过分,为什么在一个类中有一个模板虚拟成员是没有意义的 考虑抽象基类列表,其中包含。。。由此派生的LinkedList和ArrayList 如果列表存储的类型有一个标识的概念,而不是字符串或int,没有任何合理的==,我不会在这里显示POD,您可能需要一个方法 虚拟bool containsT&what const;和 虚拟整数索引&what const; 但是,如果它是一个没有标识的类型,如您想要的字符串或数字: 虚拟整数countOccurrencesT&what const;和 虚拟整数findT&what,整数出现率=0常量 说 这不能使用::std::enable_完成,如果是这样,则必须执行以下操作:C++::STD::EnableαIF和Virtual:,c++,c++11,C++,C++11,我已经扫描了答案,但是。。。这些问题似乎很愚蠢 我非常高兴,也完全理解我怎么强调都不过分,为什么在一个类中有一个模板虚拟成员是没有意义的 考虑抽象基类列表,其中包含。。。由此派生的LinkedList和ArrayList 如果列表存储的类型有一个标识的概念,而不是字符串或int,没有任何合理的==,我不会在这里显示POD,您可能需要一个方法 虚拟bool containsT&what const;和 虚拟整数索引&what const; 但是,如果它是一个没有标识的类型,如您想要的字符串或数字:
template<class T, bool HAS_IDENTITY> class List;
template<class T> class List<false> {
virtual int countOccurrences(T& what) const=0;
virtual int find(T& what, int occurrence=0) const=0;
/*other stuff*/
};
template<class T> class List<true> {
virtual bool contains(T& what) const =0;
virtual int index(T& what) const =0;
/*other stuff*/
};
这并不是很糟糕,但是有很多代码重复,我只有在必要的时候才会被弄湿
如果我将公共代码隐藏在基类中,会更好一些
我的问题涉及到用这种方法进行扩展,这里我们有一个布尔,给出两个专业,假设我有n个布尔,那么有2^n个专业,我看不出我需要超过4个的情况,但仍然涉及16个类!3人8人,不太好
假设我有一个枚举和一个布尔,那么我有2个枚举计数专门化
从远到快
以前我们使用宏来定义类,它会使用类名中的操作符来破坏它,就像模板一样。我必须说,虽然我现在很喜欢你和朋友
有没有人能告诉我解决这个问题的方法 只是一个q&d技巧,但它应该提供一些提示 我知道有人甚至可以除掉那个丑八怪,但我现在看不出来 编辑7月6日 我让ansatz的使用更加无缝。 概念标识的编译时测试,显然是问题开放者的目标,需要对概念标识进行编译时测试
//T t1, t2;
(t1 == t2) == (&t1 == &t2);
这是不可能的。
因此,我引入了功能列表的概念,以便于手动分配这些功能
#include <iostream>
#include <typeinfo>
#include <type_traits>
#ifdef __GNUG__
#include <cxxabi.h>
auto type_str = [](const std::type_info& ti) {
int stat;
return abi::__cxa_demangle(ti.name(), 0, 0, &stat);
};
#else
#warning untested
auto type_str = [](const std::type_info& ti) {
return ti.name();
};
#endif
typedef int Feature;
const Feature HAS_IDENTITY = 1;
const Feature HAS_FOOBAR = 2;
const Feature HAS_NO_IDENTITY = -HAS_IDENTITY;
const Feature HAS_NO_FOOBAR = -HAS_FOOBAR;
const Feature _TERM_ = 0;
template<typename T, Feature F>
struct has_feature : std::false_type {};
template<int N , int M>
struct is_greater {
constexpr static bool value = N > M;
};
namespace detail {
template<class T, Feature... Fs> struct List {}; // primary template
template<class T, Feature F>
struct List<T,F> {};
template<class T, Feature F, Feature... Fs>
struct List<T,F,Fs...>
: virtual public
std::conditional<
has_feature<T,F>::value,
List<T, F>,
List<T, -F>
>::type,
virtual public
std::conditional<
is_greater<sizeof...(Fs),0>::value,
List<T, Fs...>,
List<T, _TERM_>
> ::type {};
template<class T> struct List<T, _TERM_> {};
template<class T>
struct List<T,HAS_NO_FOOBAR> {
virtual std::string hello() const /* = 0;*/ {
return std::string("\"What the foo is FOOBAR?\", askes ") + type_str(typeid(T));
}
};
template<class T>
struct List<T,HAS_FOOBAR> {
virtual std::string hello() const /* = 0;*/ {
return std::string("\"For sure I'm FOOBAR\", says ") + type_str(typeid(T));
}
};
template<class T>
struct List<T,HAS_NO_IDENTITY> {
virtual int index(const T& what) const /* = 0;*/ {
return 137;
}
};
template<class T>
struct List<T,HAS_IDENTITY> {
virtual int index(const T& what) const /* = 0;*/ {
return 42;
}
};
template<typename T>
using Feature_Aware_List = List<T,HAS_IDENTITY,HAS_FOOBAR, /* all Features incuding*/_TERM_>;
} //namespace detail
template<typename T>
using List = detail::Feature_Aware_List<T>;
struct Gadget {
bool operator== (const Gadget& rhs) const {
return this == &rhs;
}
};
struct Gimmick {
bool operator== (const Gimmick& rhs) const {
return this == &rhs;
}
};
template<Feature F>
struct FeatureList {};
template<>
struct FeatureList<HAS_IDENTITY>
: public Gadget,
public Gimmick
/**/
{};
#include <valarray>
template<>
struct FeatureList<HAS_FOOBAR>
: public std::valarray<float>
/**/
{};
template<class T>
struct has_feature<T, HAS_IDENTITY>
: public std::conditional<
std::is_base_of<T, FeatureList<HAS_IDENTITY>>::value,
std::true_type,
std::false_type
>::type {};
template<class T>
struct has_feature<T, HAS_FOOBAR>
: public std::conditional<
std::is_base_of<T, FeatureList<HAS_FOOBAR>>::value,
std::true_type,
std::false_type
>::type {};
int main() {
List<Gadget> l1 ;
List<std::valarray<float>> l2;
std::cout << l1.hello() << " #" << l1.index(Gadget()) << std::endl;
std::cout << l2.hello() << " #" << l2.index(std::valarray<float>()) << std::endl;
}
输出:
"What the foo is FOOBAR?", askes Gadget #42
"For sure I'm FOOBAR", says std::valarray<float> #137
应该自我解释,没有实现特定的列表功能,这只是模拟您可以使用模板策略:
template<class T, bool HAS_IDENTITY> class ListIdentityPolicy;
template<class T> class ListIdentityPolicy<T, false> {
virtual int countOccurrences(T& what) const = 0;
virtual int find(T& what, int occurrence = 0) const = 0;
};
template<class T> class ListIdentityPolicy<T, true> {
virtual bool contains(T& what) const = 0;
virtual int index(T& what) const = 0;
};
template<class T, bool HAS_FOOBAR> struct ListFoobarPolicy;
template<class T> struct ListFoobarPolicy<T, false> {
virtual void foo() = 0;
};
template<class T> struct ListFoobarPolicy<T, true> {
virtual void bar() = 0;
};
template <class T> class List
: public ListIdentityPolicy<T, HasIdentity<T>::value>
, public ListFoobarPolicy<T, HasFoobar<T>::value>
{
public:
/*other stuff*/
};
所以恒等式的概念意味着可以使用运算符==?我不知道如何计算一个不具有相等可比性的类型的出现次数,但我认为这与回答您的问题无关。@Praetorian字符串没有标识,如果我在内存中的不同位置给您两个字符串,它们是不不同的,那么可以合理地定义一个==。一个具有身份的类型使得事物可能具有相同的位,例如,在一个名字和年龄表中记录,一个ID或身份可以将两个同名的人分开。在GUI程序中,我可以打开两个相同的框架,它们具有标识并且明显不同,这就是为什么sizeofstruct{}==1。因此@Praetorian在这种情况下,如果列表存储的是具有标识的内容,例如框架,countoccurrencess和find都是愚蠢的,contains和index都是有意义的。当现实世界中的性能如:发挥作用时,这个概念就有点模糊了:P一般来说,如果C++中使用的是一个引用或指针,那么C++中的值通过的任何东西都是缺少身份的。为什么不添加const到那些引用参数?模板类列表应该是模板类列表。
template <class T> class List
{
public:
enum Impl {
LinkedList = 0,
ArrayList,
};
List(Impl i) : pimpl(makePimpl(i)) {}
List(List const& other) : pimpl(other.pimpl->clone())
List& operator=(List const& other) { pimpl = other.pimpl->clone(); }
int count(T& what) const
{ static_assert(! HasIdentity<T>::value, "oops"); return pimpl->count(what); }
int find(T& what, int n = 0) const
{ static_assert(! HasIdentity<T>::value, "oops"); return pimpl->find(what, n); }
bool contains(T& what) const
{ static_assert(HasIdentity<T>::value, "oops"); return pimpl->contains(what); }
int index(T& what) const
{ static_assert(HasIdentity<T>::value, "oops"); return pimpl->index(what); }
void foo()
{ static_assert(! HasFoobar<T>::value, "oops"); pimpl->foo(); }
void bar()
{ static_assert(HasFoobar<T>::value, "oops"); pimpl->bar(); }
private:
struct AbstractPimpl
{
virtual std::unique_ptr<AbstractPimpl> clone() const = 0;
virtual int count(T& what) const = 0;
virtual int find(T& what, int n = 0) const = 0;
virtual bool contains(T& what) const = 0;
virtual int index(T& what) const = 0;
virtual void foo() = 0;
virtual void bar() = 0;
};
struct LinkedListPimpl : public AbstractPimpl
{
std::unique_ptr<AbstractPimpl> clone() override;
int count(T& what) const override;
int find(T& what, int n = 0) const override;
bool contains(T& what) const override;
int index(T& what) const override;
void foo() override;
void bar() override;
/* ... */
};
struct ArrayListPimpl : public AbstractPimpl
{
std::unique_ptr<AbstractPimpl> clone() override;
virtual int count(T& what) const override;
virtual int find(T& what, int n = 0) const override;
virtual bool contains(T& what) const override;
virtual int index(T& what) const override;
virtual void foo() override;
virtual void bar() override;
/* ... */
};
std::unique_ptr<AbstractPimpl> pimpl;
static std::unique_ptr<AbstractPimpl> makePimpl(Impl i) {
switch (i) {
LinkedList: default:
return std::make_unique<LinkedListPimpl>();
ArrayList:
return std::make_unique<ArrayListPimpl>();
}
}
};