有没有一种方法可以执行“if(condition)typedef ...”?

18

如果且仅如果满足编译时条件,我想执行一次typedef。如果条件不满足,则根本不应执行typedef

C++11是否支持这种操作?

示例:

class A {
  std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1".
  std::conditional_typedef<false,int,myType2>; // Does nothing at all.
};

我正在寻找这个虚构的 std::conditional_typedef


3
你能否提供一些使用那个理论上的 if(...) typedef ...; 的示例代码?特别是,如果这个typedef没有被“执行”,那么使用该typedef的代码会发生什么? - Quentin
11
std::enable_if 是一个用于编写模板函数或类时,根据条件来启用或禁用重载的类型特性。如果条件为真,则 std::enable_if 的第二个参数为该类型,否则没有第二个参数,从而导致编译器无法匹配此版本的函数或类模板。该特性通常与模板元编程结合使用,用于提供更具有泛化性和可扩展性的代码实现。 - Danh
1
根据条件,专业化可能已经足够了... - W.F.
1
一个简单的近似解决方案是有条件地typedef到所请求的类型,或者typedef到在大多数情况下无法使用的类型,例如void。这是否适用于您的情况? - Quentin
3
有这个受尊敬的 #ifdef 么? - Jack Aidley
显示剩余3条评论
3个回答

20

另一种方法可以从基类的专业化中传递

// foo is a light struct (only a typedef or not at all) that can be
// developed in two versions

template <bool>
struct foo;

template <>
struct foo<true>
 { typedef int myType1; }; // or using myType1 = int;

template <>
struct foo<false>
 { };

template <bool B>
struct bar : public foo<B> // B can be a type_traits value derived
                           // from template arguments for bar
 {
   // potential complex struct or class, developed only one time 
 };


int main()
 {
   bar<true>::myType1 mt1 { 1 };
   // bar<false>::myType1 mt2 { 1 }; error: ‘myType1’ is not a member of ‘bar<false>’
 }

使用继承似乎是解决任务的一种非常自然的方式。 - ManuelAtWork
1
不使用派生的 bar,直接使用 foo<true>::myType1 mt1 {1} 行不行? - chi
5
可以的。使用基类(依我看)的好处是,你可以仅仅用一个(或者不用)typedef就能够开发出两个不同的简单轻量级类的特化版本;这使得你可以开发出一个单一的派生类版本,使其变得更加复杂。 - max66
1
@max66:尽管这在技术上使用了继承,但我更倾向于将其标记为混入。在模板中,这是一种非常自然的解决方案。 - Matthieu M.
@MatthieuM. - 嗯...我不是专家,也不擅长标记,但是使用模板,我觉得非常自然。 - max66

16

很遗憾,所期望的语法无法实现,因为传递给模板实例化的名称必须已经定义。在您的情况下,从编译器的角度来看,myType1myType2都不会命名任何东西。但是,如果您不坚持使用您提到的语法,您可以尝试使用以下方法:std::enable_if

#include <type_traits>

struct A {
    struct myType1: std::enable_if<true, int> { }; //std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1".
    struct myType2: std::enable_if<false, int> { }; //std::conditional_typedef<false,int,myType2>; // Does nothing at all.

};

int main() {
    A::myType1::type i;
    //A::myType2::type i2; // causes error: no type named 'type' in 'A::myType2'
    (void)i;
}

[在线演示]


编辑:

我想到了另一种方法(利用使用默认模板参数):

#include <type_traits>

struct A {
    template <class T = int>
    using myType1 = typename std::enable_if<true, T>::type;
    template <class T = int>
    using myType2 = typename std::enable_if<false, T>::type;
};

int main() {
    A::myType1<> i;
    //A::myType2<> j;
    (void)i;
}

[live demo]


2
与std :: enable_if类似,如果您想使用自己的名称而不必执行A :: mytype1 :: type,则可以使您的类从执行typedef的模板继承。缺点是,如果您要经常这样做,则必须从多个结构体中继承。
namespace impl {
    template<bool, typename> struct A;
    template<typename T> struct A<true, T>{ typedef T mytype1; };
    template<typename T> struct A<false, T> {};
}

struct A : public impl::A<condition, int> {
    //If condition is met, then ::mytype1 will be defined as a typedef int
};

int main() {
    A::mytype1 i; //Will fail if condition wasn't met
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接