2016-11-18 67 views
0

类似于Conditional compile-time inclusion/exclusion of code based on template argument(s)?基于模板争议的条件相同模板类代码?

(顺便说一句答案2在上面的问题不编译在所有)

(C++ 11及以上)

我下面的类的说明中,想外::内< ...>以便用作模板参数等。

template<typename T> 
struct Outer { 
    __enable_if__(cond_1<T>()) { 
    // Does not compile if T fails cond_1 
    template<typename> Inner { ... }; 
    } 
    __enable_if__(cond_2<T>()) { 
    // Does not compile if T fails cond_2 
    template<typename> Inner { ... }; 
    } 
}; 

我只能想到某事。如下所示。

#include <type_traits> 

struct BaseA { static constexpr int va = 111; }; 
struct BaseB { static constexpr int vb = 222; }; 

struct C : public BaseA {}; 
struct D : public BaseB {}; 

template<typename T> 
struct Outer { 
    template<typename, int selector> struct InnerImpl; 

    template<typename S> struct InnerImpl<S, 1> { static constexpr int v = T::va; }; 
    template<typename S> struct InnerImpl<S, 2> { static constexpr int v = T::vb; }; 

    static constexpr int computeSelector() { 
    // Could be less horrible with C++14 constexpr functions 
    // std::is_base_of acts as a demo of complex compile-time conditions 
    return std::is_base_of<BaseA, T>::value + std::is_base_of<BaseB, T>::value * 2; 
    } // **1 

    template<typename S> using Inner = InnerImpl<S, computeSelector()>; 
}; 

问题是,这种方式根本无法扩展。

外部依赖于全部可能的T,很容易导致循环标头依赖。

是否有任何解决方案外部不依赖于T?

+1

您是否只需要'Inner '的两个潜在实现?你想以什么方式扩展? –

+0

超过两个潜在的实现。在真实场景中,BaseA,BaseB和Outer存在于不同的头文件(以及逻辑上不同的模块)中。因此,我想消除外部对所有相关类型的影响。 – user2771324

+0

我的愿望是:如果在翻译单元中没有使用类型Outer,翻译单元不必包含BaseA,BaseB等所有相关的标题。 – user2771324

回答

0

不确定要理解你的问题,但我已经试图证实你的例子。

以下解决方案有什么问题?

#include <iostream> 
#include <type_traits> 

struct BaseA { static constexpr int va = 111; }; 
struct BaseB { static constexpr int vb = 222; }; 

struct C : public BaseA {}; 
struct D : public BaseB {}; 

template<typename T> 
struct Outer 
{ 
    template <typename S, bool B = true> 
    struct InnerI; 

    template <typename S> 
    struct InnerI<S, std::is_base_of<BaseA, T>::value> 
    { static constexpr int v { T::va }; }; 

    template <typename S> 
    struct InnerI<S, std::is_base_of<BaseB, T>::value> 
    { static constexpr int v { T::vb }; }; 

    template <typename S> 
    using Inner = InnerI<S>; 
}; 


int main() 
{ 
    std::cout << Outer<C>::Inner<int>::v << std::endl; // print 111 
    std::cout << Outer<D>::Inner<long>::v << std::endl; // print 222 
    // std::cout << Outer<int>::Inner<char>::v << std::endl; // compilation error 
} 
+0

我的愿望是:如果类型Outer未用于翻译单元,翻译单元不必包含BaseA,BaseB等的所有相关头文件。std :: is_base_of需要定义参数类型,这将引入头文件依赖性。 – user2771324