我使用static_assert
获得了相当简单的功能。问题是我希望static_assert
涉及函数声明中涉及的行为 - 特别是推断返回类型。似乎没有任何地方可以插入static_assert
以便我可以在编译器无法推断出返回类型之前触发它。
到目前为止,我将返回类型推导和静态断言放在结构中。这将触发断言,这很好,但它仍会在类型推导上产生错误,这是我想要消除的噪音。
#include <type_traits>
#include <functional>
#include <memory>
#include <map>
#include <iostream>
#include <string>
#include <cstdio>
#include <tuple>
#include <sstream>
#include <vector>
#include <algorithm>
template<typename T, typename X> struct is_addable {
template<typename Test, typename Test2> static char test(decltype(*static_cast<Test*>(nullptr) + *static_cast<Test2*>(nullptr))*);
template<typename Test, typename Test2> static int test(...);
static const bool value = std::is_same<char, decltype(test<T, X>(nullptr))>::value;
};
template<typename T, typename X> struct is_addable_fail {
static const bool value = is_addable<T, X>::value;
static_assert(value, "Must be addable!");
typedef decltype(*static_cast<T*>(nullptr) + *static_cast<X*>(nullptr)) lvalue_type;
};
template<typename T1, typename T2> auto Add(T1&& t1, T2&& t2) -> typename is_addable_fail<T1, T2>::lvalue_type {
return std::forward<T1>(t1) + std::forward<T2>(t2);
}
struct f {};
int main() {
std::cout << Add(std::string("Hello"), std::string(" world!"));
Add(f(), f());
}
答案 0 :(得分:0)
由于候选集的构建方式和SFINAE,这是不可能的。如果你可以在完全确定函数的签名之前断言,那么在确定该函数是将要使用的函数之前,需要断言。
步骤的顺序基本上是:
你什么时候想要断言?
如果你在参数替换期间触发它,那么你排除了SFINAE,如果你在此之后的任何时候触发它,那么返回类型已经确定(太晚了)。
答案 1 :(得分:0)
虽然我可能会误解这个问题, SFINAE是否满足以下目的?
template<typename T = int> void Add(...) {
static_assert(sizeof(T) == 0, "Must be addable!");
}
template<typename T1, typename T2> auto Add(T1&& t1, T2&& t2) ->
decltype(std::forward<T1>(t1) + std::forward<T2>(t2)) {
return std::forward<T1>(t1) + std::forward<T2>(t2);
}
以下是对ideone的测试。
缺点是Add
必须重复。
修改强> 虽然我不完全确定这是严格的标准符合,但是 以下是解决方案的帮助? (a test on ideone)
template<typename T1, typename T2> void Add(T1 volatile&&, T2 volatile&&) {
static_assert(sizeof(T1) == 0, "Must be addable!");
}